diff options
Diffstat (limited to 'web/src')
33 files changed, 10354 insertions, 16092 deletions
diff --git a/web/src/flows.json b/web/src/flows.json deleted file mode 100644 index bdbfd5cc..00000000 --- a/web/src/flows.json +++ /dev/null @@ -1,2012 +0,0 @@ -[{ - "request": { - "timestamp_end": 1410651311.107, - "timestamp_start": 1410651311.106, - "form_in": "relative", - "headers": [ - [ - "Host", - "news.ycombinator.com" - ], - [ - "User-Agent", - "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" - ], - [ - "Accept", - "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" - ], - [ - "Accept-Language", - "de,en-US;q=0.7,en;q=0.3" - ], - [ - "Accept-Encoding", - "gzip, deflate" - ], - [ - "Cookie", - "__cfduid=d0486ff404fe3beb320f15e958861aaea1410651010546" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Pragma", - "no-cache" - ], - [ - "Cache-Control", - "no-cache" - ] - ], - "host": "news.ycombinator.com", - "form_out": "relative", - "path": "/", - "method": "GET", - "scheme": "https", - "port": 443, - "httpversion": [ - 1, - 1 - ] - }, - "server_conn": { - "timestamp_tcp_setup": 1410651311.055, - "state": [], - "timestamp_ssl_setup": 1410651311.096, - "sni": "news.ycombinator.com", - "timestamp_start": 1410651311.04, - "address": { - "use_ipv6": false, - "address": [ - "news.ycombinator.com", - 443 - ] - }, - "timestamp_end": null, - "source_address": { - "use_ipv6": false, - "address": [ - "192.168.1.117", - 63383 - ] - }, - "ssl_established": true - }, - "client_conn": { - "timestamp_start": 1410651310.36, - "address": { - "use_ipv6": false, - "address": [ - "127.0.0.1", - 63380 - ] - }, - "timestamp_ssl_setup": 1410651311.105, - "timestamp_end": null, - "clientcert": null, - "ssl_established": true - }, - "conntype": "http", - "version": [ - 0, - 11 - ], - "error": null, - "response": { - "code": 200, - "headers": [ - [ - "Server", - "cloudflare-nginx" - ], - [ - "Date", - "Sat, 13 Sep 2014 23:35:08 GMT" - ], - [ - "Content-Type", - "text/html; charset=utf-8" - ], - [ - "Transfer-Encoding", - "chunked" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Vary", - "Accept-Encoding" - ], - [ - "Cache-Control", - "private" - ], - [ - "X-Frame-Options", - "DENY" - ], - [ - "Cache-Control", - "max-age=0" - ], - [ - "Strict-Transport-Security", - "max-age=31556900; includeSubDomains" - ], - [ - "CF-RAY", - "169828d0108e088d-FRA" - ], - [ - "Content-Encoding", - "gzip" - ] - ], - "timestamp_start": 1410651311.6, - "msg": "OK", - "timestamp_end": 1410651311.603, - "httpversion": [ - 1, - 1 - ] - } -}, -{ - "request": { - "timestamp_end": 1410651311.657, - "timestamp_start": 1410651311.653, - "form_in": "relative", - "headers": [ - [ - "Host", - "news.ycombinator.com" - ], - [ - "User-Agent", - "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" - ], - [ - "Accept", - "text/css,*/*;q=0.1" - ], - [ - "Accept-Language", - "de,en-US;q=0.7,en;q=0.3" - ], - [ - "Accept-Encoding", - "gzip, deflate" - ], - [ - "Referer", - "https://news.ycombinator.com/" - ], - [ - "Cookie", - "__cfduid=d0486ff404fe3beb320f15e958861aaea1410651010546" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Pragma", - "no-cache" - ], - [ - "Cache-Control", - "no-cache" - ] - ], - "host": "news.ycombinator.com", - "form_out": "relative", - "path": "/news.css?IZYAdhDe5bN6BGyHv1jq", - "method": "GET", - "scheme": "https", - "port": 443, - "httpversion": [ - 1, - 1 - ] - }, - "server_conn": { - "timestamp_tcp_setup": 1410651311.055, - "state": [], - "timestamp_ssl_setup": 1410651311.096, - "sni": "news.ycombinator.com", - "timestamp_start": 1410651311.04, - "address": { - "use_ipv6": false, - "address": [ - "news.ycombinator.com", - 443 - ] - }, - "timestamp_end": null, - "source_address": { - "use_ipv6": false, - "address": [ - "192.168.1.117", - 63383 - ] - }, - "ssl_established": true - }, - "client_conn": { - "timestamp_start": 1410651310.36, - "address": { - "use_ipv6": false, - "address": [ - "127.0.0.1", - 63380 - ] - }, - "timestamp_ssl_setup": 1410651311.105, - "timestamp_end": null, - "clientcert": null, - "ssl_established": true - }, - "conntype": "http", - "version": [ - 0, - 11 - ], - "error": null, - "response": { - "code": 200, - "headers": [ - [ - "Server", - "cloudflare-nginx" - ], - [ - "Date", - "Sat, 13 Sep 2014 23:35:08 GMT" - ], - [ - "Content-Type", - "text/css" - ], - [ - "Transfer-Encoding", - "chunked" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Last-Modified", - "Fri, 01 Aug 2014 04:27:14 GMT" - ], - [ - "Vary", - "Accept-Encoding" - ], - [ - "Expires", - "Mon, 29 Jul 2024 04:27:14 GMT" - ], - [ - "Cache-Control", - "max-age=311575926" - ], - [ - "Cache-Control", - "public" - ], - [ - "CF-RAY", - "169828d38096088d-FRA" - ], - [ - "Content-Encoding", - "gzip" - ] - ], - "timestamp_start": 1410651312.167, - "msg": "OK", - "timestamp_end": 1410651312.17, - "httpversion": [ - 1, - 1 - ] - } -}, -{ - "request": { - "timestamp_end": 1410651312.362, - "timestamp_start": 1410651312.359, - "form_in": "relative", - "headers": [ - [ - "Host", - "news.ycombinator.com" - ], - [ - "User-Agent", - "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" - ], - [ - "Accept", - "image/png,image/*;q=0.8,*/*;q=0.5" - ], - [ - "Accept-Language", - "de,en-US;q=0.7,en;q=0.3" - ], - [ - "Accept-Encoding", - "gzip, deflate" - ], - [ - "Referer", - "https://news.ycombinator.com/" - ], - [ - "Cookie", - "__cfduid=d0486ff404fe3beb320f15e958861aaea1410651010546" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Pragma", - "no-cache" - ], - [ - "Cache-Control", - "no-cache" - ] - ], - "host": "news.ycombinator.com", - "form_out": "relative", - "path": "/s.gif", - "method": "GET", - "scheme": "https", - "port": 443, - "httpversion": [ - 1, - 1 - ] - }, - "server_conn": { - "timestamp_tcp_setup": 1410651312.303, - "state": [], - "timestamp_ssl_setup": 1410651312.349, - "sni": "news.ycombinator.com", - "timestamp_start": 1410651312.287, - "address": { - "use_ipv6": false, - "address": [ - "news.ycombinator.com", - 443 - ] - }, - "timestamp_end": null, - "source_address": { - "use_ipv6": false, - "address": [ - "192.168.1.117", - 63391 - ] - }, - "ssl_established": true - }, - "client_conn": { - "timestamp_start": 1410651312.193, - "address": { - "use_ipv6": false, - "address": [ - "127.0.0.1", - 63386 - ] - }, - "timestamp_ssl_setup": 1410651312.358, - "timestamp_end": null, - "clientcert": null, - "ssl_established": true - }, - "conntype": "http", - "version": [ - 0, - 11 - ], - "error": null, - "response": { - "code": 200, - "headers": [ - [ - "Server", - "cloudflare-nginx" - ], - [ - "Date", - "Sat, 13 Sep 2014 23:35:08 GMT" - ], - [ - "Content-Type", - "image/gif" - ], - [ - "Content-Length", - "43" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Last-Modified", - "Tue, 12 Mar 2013 09:06:31 GMT" - ], - [ - "ETag", - "\"513ef017-2b\"" - ], - [ - "Expires", - "Fri, 31 Mar 2023 21:06:02 GMT" - ], - [ - "Cache-Control", - "public, max-age=269645454" - ], - [ - "CF-Cache-Status", - "HIT" - ], - [ - "Vary", - "Accept-Encoding" - ], - [ - "Accept-Ranges", - "bytes" - ], - [ - "CF-RAY", - "169828d7e771088d-FRA" - ] - ], - "timestamp_start": 1410651312.383, - "msg": "OK", - "timestamp_end": 1410651312.393, - "httpversion": [ - 1, - 1 - ] - } -}, -{ - "request": { - "timestamp_end": 1410651312.389, - "timestamp_start": 1410651312.368, - "form_in": "relative", - "headers": [ - [ - "Host", - "news.ycombinator.com" - ], - [ - "User-Agent", - "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" - ], - [ - "Accept", - "image/png,image/*;q=0.8,*/*;q=0.5" - ], - [ - "Accept-Language", - "de,en-US;q=0.7,en;q=0.3" - ], - [ - "Accept-Encoding", - "gzip, deflate" - ], - [ - "Referer", - "https://news.ycombinator.com/news.css?IZYAdhDe5bN6BGyHv1jq" - ], - [ - "Cookie", - "__cfduid=d0486ff404fe3beb320f15e958861aaea1410651010546" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Pragma", - "no-cache" - ], - [ - "Cache-Control", - "no-cache" - ] - ], - "host": "news.ycombinator.com", - "form_out": "relative", - "path": "/grayarrow.gif", - "method": "GET", - "scheme": "https", - "port": 443, - "httpversion": [ - 1, - 1 - ] - }, - "server_conn": { - "timestamp_tcp_setup": 1410651312.307, - "state": [], - "timestamp_ssl_setup": 1410651312.355, - "sni": "news.ycombinator.com", - "timestamp_start": 1410651312.291, - "address": { - "use_ipv6": false, - "address": [ - "news.ycombinator.com", - 443 - ] - }, - "timestamp_end": null, - "source_address": { - "use_ipv6": false, - "address": [ - "192.168.1.117", - 63393 - ] - }, - "ssl_established": true - }, - "client_conn": { - "timestamp_start": 1410651312.2, - "address": { - "use_ipv6": false, - "address": [ - "127.0.0.1", - 63387 - ] - }, - "timestamp_ssl_setup": 1410651312.368, - "timestamp_end": null, - "clientcert": null, - "ssl_established": true - }, - "conntype": "http", - "version": [ - 0, - 11 - ], - "error": null, - "response": { - "code": 200, - "headers": [ - [ - "Server", - "cloudflare-nginx" - ], - [ - "Date", - "Sat, 13 Sep 2014 23:35:08 GMT" - ], - [ - "Content-Type", - "image/gif" - ], - [ - "Content-Length", - "111" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Last-Modified", - "Tue, 12 Mar 2013 09:06:31 GMT" - ], - [ - "ETag", - "\"513ef017-6f\"" - ], - [ - "Expires", - "Sat, 01 Apr 2023 05:56:11 GMT" - ], - [ - "Cache-Control", - "public, max-age=269677263" - ], - [ - "CF-Cache-Status", - "HIT" - ], - [ - "Vary", - "Accept-Encoding" - ], - [ - "Accept-Ranges", - "bytes" - ], - [ - "CF-RAY", - "169828d81430088d-FRA" - ] - ], - "timestamp_start": 1410651312.409, - "msg": "OK", - "timestamp_end": 1410651312.412, - "httpversion": [ - 1, - 1 - ] - } -}, -{ - "request": { - "timestamp_end": 1410651312.386, - "timestamp_start": 1410651312.368, - "form_in": "relative", - "headers": [ - [ - "Host", - "news.ycombinator.com" - ], - [ - "User-Agent", - "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" - ], - [ - "Accept", - "image/png,image/*;q=0.8,*/*;q=0.5" - ], - [ - "Accept-Language", - "de,en-US;q=0.7,en;q=0.3" - ], - [ - "Accept-Encoding", - "gzip, deflate" - ], - [ - "Referer", - "https://news.ycombinator.com/" - ], - [ - "Cookie", - "__cfduid=d0486ff404fe3beb320f15e958861aaea1410651010546" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Pragma", - "no-cache" - ], - [ - "Cache-Control", - "no-cache" - ] - ], - "host": "news.ycombinator.com", - "form_out": "relative", - "path": "/y18.gif", - "method": "GET", - "scheme": "https", - "port": 443, - "httpversion": [ - 1, - 1 - ] - }, - "server_conn": { - "timestamp_tcp_setup": 1410651312.303, - "state": [], - "timestamp_ssl_setup": 1410651312.355, - "sni": "news.ycombinator.com", - "timestamp_start": 1410651312.287, - "address": { - "use_ipv6": false, - "address": [ - "news.ycombinator.com", - 443 - ] - }, - "timestamp_end": null, - "source_address": { - "use_ipv6": false, - "address": [ - "192.168.1.117", - 63392 - ] - }, - "ssl_established": true - }, - "client_conn": { - "timestamp_start": 1410651312.192, - "address": { - "use_ipv6": false, - "address": [ - "127.0.0.1", - 63385 - ] - }, - "timestamp_ssl_setup": 1410651312.368, - "timestamp_end": null, - "clientcert": null, - "ssl_established": true - }, - "conntype": "http", - "version": [ - 0, - 11 - ], - "error": null, - "response": { - "code": 200, - "headers": [ - [ - "Server", - "cloudflare-nginx" - ], - [ - "Date", - "Sat, 13 Sep 2014 23:35:08 GMT" - ], - [ - "Content-Type", - "image/gif" - ], - [ - "Content-Length", - "100" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Last-Modified", - "Tue, 12 Mar 2013 09:06:31 GMT" - ], - [ - "ETag", - "\"513ef017-64\"" - ], - [ - "Expires", - "Sat, 01 Apr 2023 04:28:54 GMT" - ], - [ - "Cache-Control", - "public, max-age=269672026" - ], - [ - "CF-Cache-Status", - "HIT" - ], - [ - "Vary", - "Accept-Encoding" - ], - [ - "Accept-Ranges", - "bytes" - ], - [ - "CF-RAY", - "169828d8109a088d-FRA" - ] - ], - "timestamp_start": 1410651312.413, - "msg": "OK", - "timestamp_end": 1410651312.416, - "httpversion": [ - 1, - 1 - ] - } -}, -{ - "request": { - "timestamp_end": 1410651373.965, - "timestamp_start": 1410651373.963, - "form_in": "absolute", - "headers": [ - [ - "Host", - "mitmproxy.org" - ], - [ - "User-Agent", - "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" - ], - [ - "Accept", - "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" - ], - [ - "Accept-Language", - "de,en-US;q=0.7,en;q=0.3" - ], - [ - "Accept-Encoding", - "gzip, deflate" - ], - [ - "Connection", - "keep-alive" - ] - ], - "host": "mitmproxy.org", - "form_out": "relative", - "path": "/", - "method": "GET", - "scheme": "http", - "port": 80, - "httpversion": [ - 1, - 1 - ] - }, - "server_conn": { - "timestamp_tcp_setup": 1410651374.189, - "state": [], - "timestamp_ssl_setup": null, - "sni": null, - "timestamp_start": 1410651373.985, - "address": { - "use_ipv6": false, - "address": [ - "mitmproxy.org", - 80 - ] - }, - "timestamp_end": null, - "source_address": { - "use_ipv6": false, - "address": [ - "192.168.1.117", - 63404 - ] - }, - "ssl_established": false - }, - "client_conn": { - "timestamp_start": 1410651373.958, - "address": { - "use_ipv6": false, - "address": [ - "127.0.0.1", - 63403 - ] - }, - "timestamp_ssl_setup": null, - "timestamp_end": null, - "clientcert": null, - "ssl_established": false - }, - "conntype": "http", - "version": [ - 0, - 11 - ], - "error": null, - "response": { - "code": 200, - "headers": [ - [ - "Server", - "nginx/1.1.19" - ], - [ - "Date", - "Sat, 13 Sep 2014 23:36:10 GMT" - ], - [ - "Content-Type", - "text/html" - ], - [ - "Last-Modified", - "Wed, 26 Feb 2014 19:58:20 GMT" - ], - [ - "Transfer-Encoding", - "chunked" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Vary", - "Accept-Encoding" - ], - [ - "Content-Encoding", - "gzip" - ] - ], - "timestamp_start": 1410651374.365, - "msg": "OK", - "timestamp_end": 1410651374.366, - "httpversion": [ - 1, - 1 - ] - } -}, -{ - "request": { - "timestamp_end": 1410651374.391, - "timestamp_start": 1410651374.387, - "form_in": "absolute", - "headers": [ - [ - "Host", - "mitmproxy.org" - ], - [ - "User-Agent", - "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" - ], - [ - "Accept", - "text/css,*/*;q=0.1" - ], - [ - "Accept-Language", - "de,en-US;q=0.7,en;q=0.3" - ], - [ - "Accept-Encoding", - "gzip, deflate" - ], - [ - "Referer", - "http://mitmproxy.org/" - ], - [ - "Connection", - "keep-alive" - ] - ], - "host": "mitmproxy.org", - "form_out": "relative", - "path": "/01-bootstrap.min.css", - "method": "GET", - "scheme": "http", - "port": 80, - "httpversion": [ - 1, - 1 - ] - }, - "server_conn": { - "timestamp_tcp_setup": 1410651374.189, - "state": [], - "timestamp_ssl_setup": null, - "sni": null, - "timestamp_start": 1410651373.985, - "address": { - "use_ipv6": false, - "address": [ - "mitmproxy.org", - 80 - ] - }, - "timestamp_end": null, - "source_address": { - "use_ipv6": false, - "address": [ - "192.168.1.117", - 63404 - ] - }, - "ssl_established": false - }, - "client_conn": { - "timestamp_start": 1410651373.958, - "address": { - "use_ipv6": false, - "address": [ - "127.0.0.1", - 63403 - ] - }, - "timestamp_ssl_setup": null, - "timestamp_end": null, - "clientcert": null, - "ssl_established": false - }, - "conntype": "http", - "version": [ - 0, - 11 - ], - "error": null, - "response": { - "code": 200, - "headers": [ - [ - "Server", - "nginx/1.1.19" - ], - [ - "Date", - "Sat, 13 Sep 2014 23:36:10 GMT" - ], - [ - "Content-Type", - "text/css" - ], - [ - "Last-Modified", - "Wed, 26 Feb 2014 19:58:20 GMT" - ], - [ - "Transfer-Encoding", - "chunked" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Vary", - "Accept-Encoding" - ], - [ - "Content-Encoding", - "gzip" - ] - ], - "timestamp_start": 1410651374.579, - "msg": "OK", - "timestamp_end": 1410651374.58, - "httpversion": [ - 1, - 1 - ] - } -}, -{ - "request": { - "timestamp_end": 1410651374.396, - "timestamp_start": 1410651374.394, - "form_in": "absolute", - "headers": [ - [ - "Host", - "mitmproxy.org" - ], - [ - "User-Agent", - "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" - ], - [ - "Accept", - "text/css,*/*;q=0.1" - ], - [ - "Accept-Language", - "de,en-US;q=0.7,en;q=0.3" - ], - [ - "Accept-Encoding", - "gzip, deflate" - ], - [ - "Referer", - "http://mitmproxy.org/" - ], - [ - "Connection", - "keep-alive" - ] - ], - "host": "mitmproxy.org", - "form_out": "relative", - "path": "/03-sitestyle.css", - "method": "GET", - "scheme": "http", - "port": 80, - "httpversion": [ - 1, - 1 - ] - }, - "server_conn": { - "timestamp_tcp_setup": 1410651374.567, - "state": [], - "timestamp_ssl_setup": null, - "sni": null, - "timestamp_start": 1410651374.401, - "address": { - "use_ipv6": false, - "address": [ - "mitmproxy.org", - 80 - ] - }, - "timestamp_end": null, - "source_address": { - "use_ipv6": false, - "address": [ - "192.168.1.117", - 63407 - ] - }, - "ssl_established": false - }, - "client_conn": { - "timestamp_start": 1410651374.389, - "address": { - "use_ipv6": false, - "address": [ - "127.0.0.1", - 63405 - ] - }, - "timestamp_ssl_setup": null, - "timestamp_end": null, - "clientcert": null, - "ssl_established": false - }, - "conntype": "http", - "version": [ - 0, - 11 - ], - "error": null, - "response": { - "code": 200, - "headers": [ - [ - "Server", - "nginx/1.1.19" - ], - [ - "Date", - "Sat, 13 Sep 2014 23:36:11 GMT" - ], - [ - "Content-Type", - "text/css" - ], - [ - "Content-Length", - "124" - ], - [ - "Last-Modified", - "Wed, 26 Feb 2014 19:58:20 GMT" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Accept-Ranges", - "bytes" - ] - ], - "timestamp_start": 1410651374.746, - "msg": "OK", - "timestamp_end": 1410651374.747, - "httpversion": [ - 1, - 1 - ] - } -}, -{ - "request": { - "timestamp_end": 1410651374.795, - "timestamp_start": 1410651374.793, - "form_in": "absolute", - "headers": [ - [ - "Host", - "www.google-analytics.com" - ], - [ - "User-Agent", - "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" - ], - [ - "Accept", - "*/*" - ], - [ - "Accept-Language", - "de,en-US;q=0.7,en;q=0.3" - ], - [ - "Accept-Encoding", - "gzip, deflate" - ], - [ - "Referer", - "http://mitmproxy.org/" - ], - [ - "Connection", - "keep-alive" - ] - ], - "host": "www.google-analytics.com", - "form_out": "relative", - "path": "/ga.js", - "method": "GET", - "scheme": "http", - "port": 80, - "httpversion": [ - 1, - 1 - ] - }, - "server_conn": { - "timestamp_tcp_setup": 1410651374.99, - "state": [], - "timestamp_ssl_setup": null, - "sni": null, - "timestamp_start": 1410651374.974, - "address": { - "use_ipv6": false, - "address": [ - "www.google-analytics.com", - 80 - ] - }, - "timestamp_end": null, - "source_address": { - "use_ipv6": false, - "address": [ - "192.168.1.117", - 63409 - ] - }, - "ssl_established": false - }, - "client_conn": { - "timestamp_start": 1410651374.389, - "address": { - "use_ipv6": false, - "address": [ - "127.0.0.1", - 63405 - ] - }, - "timestamp_ssl_setup": null, - "timestamp_end": null, - "clientcert": null, - "ssl_established": false - }, - "conntype": "http", - "version": [ - 0, - 11 - ], - "error": null, - "response": { - "code": 200, - "headers": [ - [ - "Date", - "Sat, 13 Sep 2014 22:02:27 GMT" - ], - [ - "Expires", - "Sun, 14 Sep 2014 00:02:27 GMT" - ], - [ - "Last-Modified", - "Mon, 08 Sep 2014 18:50:13 GMT" - ], - [ - "X-Content-Type-Options", - "nosniff" - ], - [ - "Content-Type", - "text/javascript" - ], - [ - "Vary", - "Accept-Encoding" - ], - [ - "Content-Encoding", - "gzip" - ], - [ - "Server", - "Golfe2" - ], - [ - "Content-Length", - "16062" - ], - [ - "Age", - "5624" - ], - [ - "Cache-Control", - "public, max-age=7200" - ], - [ - "Alternate-Protocol", - "80:quic,p=0.002" - ] - ], - "timestamp_start": 1410651375.013, - "msg": "OK", - "timestamp_end": 1410651375.015, - "httpversion": [ - 1, - 1 - ] - } -}, -{ - "request": { - "timestamp_end": 1410651375.084, - "timestamp_start": 1410651375.078, - "form_in": "absolute", - "headers": [ - [ - "Host", - "www.google-analytics.com" - ], - [ - "User-Agent", - "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" - ], - [ - "Accept", - "image/png,image/*;q=0.8,*/*;q=0.5" - ], - [ - "Accept-Language", - "de,en-US;q=0.7,en;q=0.3" - ], - [ - "Accept-Encoding", - "gzip, deflate" - ], - [ - "Referer", - "http://mitmproxy.org/" - ], - [ - "Connection", - "keep-alive" - ] - ], - "host": "www.google-analytics.com", - "form_out": "relative", - "path": "/__utm.gif?utmwv=5.5.7&utms=1&utmn=1242429522&utmhn=mitmproxy.org&utmcs=UTF-8&utmsr=1536x864&utmvp=1091x742&utmsc=24-bit&utmul=de&utmje=1&utmfl=15.0%20r0&utmdt=mitmproxy%20-%20home&utmhid=812953117&utmr=-&utmp=%2F&utmht=1410651375077&utmac=UA-4150636-13&utmcc=__utma%3D30234659.1711188806.1410651375.1410651375.1410651375.1%3B%2B__utmz%3D30234659.1410651375.1.1.utmcsr%3D(direct)%7Cutmccn%3D(direct)%7Cutmcmd%3D(none)%3B&utmu=q~", - "method": "GET", - "scheme": "http", - "port": 80, - "httpversion": [ - 1, - 1 - ] - }, - "server_conn": { - "timestamp_tcp_setup": 1410651374.99, - "state": [], - "timestamp_ssl_setup": null, - "sni": null, - "timestamp_start": 1410651374.974, - "address": { - "use_ipv6": false, - "address": [ - "www.google-analytics.com", - 80 - ] - }, - "timestamp_end": null, - "source_address": { - "use_ipv6": false, - "address": [ - "192.168.1.117", - 63409 - ] - }, - "ssl_established": false - }, - "client_conn": { - "timestamp_start": 1410651374.389, - "address": { - "use_ipv6": false, - "address": [ - "127.0.0.1", - 63405 - ] - }, - "timestamp_ssl_setup": null, - "timestamp_end": null, - "clientcert": null, - "ssl_established": false - }, - "conntype": "http", - "version": [ - 0, - 11 - ], - "error": null, - "response": { - "code": 200, - "headers": [ - [ - "Pragma", - "no-cache" - ], - [ - "Expires", - "Wed, 19 Apr 2000 11:43:00 GMT" - ], - [ - "Last-Modified", - "Wed, 21 Jan 2004 19:51:30 GMT" - ], - [ - "X-Content-Type-Options", - "nosniff" - ], - [ - "Content-Type", - "image/gif" - ], - [ - "Date", - "Thu, 04 Sep 2014 18:39:58 GMT" - ], - [ - "Server", - "Golfe2" - ], - [ - "Content-Length", - "35" - ], - [ - "Age", - "795373" - ], - [ - "Cache-Control", - "private, no-cache, no-cache=Set-Cookie, proxy-revalidate" - ], - [ - "Alternate-Protocol", - "80:quic,p=0.002" - ] - ], - "timestamp_start": 1410651375.104, - "msg": "OK", - "timestamp_end": 1410651375.107, - "httpversion": [ - 1, - 1 - ] - } -}, -{ - "request": { - "timestamp_end": 1410651374.778, - "timestamp_start": 1410651374.766, - "form_in": "absolute", - "headers": [ - [ - "Host", - "mitmproxy.org" - ], - [ - "User-Agent", - "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" - ], - [ - "Accept", - "image/png,image/*;q=0.8,*/*;q=0.5" - ], - [ - "Accept-Language", - "de,en-US;q=0.7,en;q=0.3" - ], - [ - "Accept-Encoding", - "gzip, deflate" - ], - [ - "Referer", - "http://mitmproxy.org/" - ], - [ - "Connection", - "keep-alive" - ] - ], - "host": "mitmproxy.org", - "form_out": "relative", - "path": "/images/apple.png", - "method": "GET", - "scheme": "http", - "port": 80, - "httpversion": [ - 1, - 1 - ] - }, - "server_conn": { - "timestamp_tcp_setup": 1410651374.952, - "state": [], - "timestamp_ssl_setup": null, - "sni": null, - "timestamp_start": 1410651374.782, - "address": { - "use_ipv6": false, - "address": [ - "mitmproxy.org", - 80 - ] - }, - "timestamp_end": null, - "source_address": { - "use_ipv6": false, - "address": [ - "192.168.1.117", - 63408 - ] - }, - "ssl_established": false - }, - "client_conn": { - "timestamp_start": 1410651374.39, - "address": { - "use_ipv6": false, - "address": [ - "127.0.0.1", - 63406 - ] - }, - "timestamp_ssl_setup": null, - "timestamp_end": null, - "clientcert": null, - "ssl_established": false - }, - "conntype": "http", - "version": [ - 0, - 11 - ], - "error": null, - "response": { - "code": 200, - "headers": [ - [ - "Server", - "nginx/1.1.19" - ], - [ - "Date", - "Sat, 13 Sep 2014 23:36:11 GMT" - ], - [ - "Content-Type", - "image/png" - ], - [ - "Content-Length", - "20532" - ], - [ - "Last-Modified", - "Wed, 26 Feb 2014 19:58:20 GMT" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Accept-Ranges", - "bytes" - ] - ], - "timestamp_start": 1410651375.125, - "msg": "OK", - "timestamp_end": 1410651375.126, - "httpversion": [ - 1, - 1 - ] - } -}, -{ - "request": { - "timestamp_end": 1410651374.778, - "timestamp_start": 1410651374.766, - "form_in": "absolute", - "headers": [ - [ - "Host", - "mitmproxy.org" - ], - [ - "User-Agent", - "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" - ], - [ - "Accept", - "image/png,image/*;q=0.8,*/*;q=0.5" - ], - [ - "Accept-Language", - "de,en-US;q=0.7,en;q=0.3" - ], - [ - "Accept-Encoding", - "gzip, deflate" - ], - [ - "Referer", - "http://mitmproxy.org/" - ], - [ - "Connection", - "keep-alive" - ] - ], - "host": "mitmproxy.org", - "form_out": "relative", - "path": "/images/mitmproxy-small.png", - "method": "GET", - "scheme": "http", - "port": 80, - "httpversion": [ - 1, - 1 - ] - }, - "server_conn": { - "timestamp_tcp_setup": 1410651374.189, - "state": [], - "timestamp_ssl_setup": null, - "sni": null, - "timestamp_start": 1410651373.985, - "address": { - "use_ipv6": false, - "address": [ - "mitmproxy.org", - 80 - ] - }, - "timestamp_end": null, - "source_address": { - "use_ipv6": false, - "address": [ - "192.168.1.117", - 63404 - ] - }, - "ssl_established": false - }, - "client_conn": { - "timestamp_start": 1410651373.958, - "address": { - "use_ipv6": false, - "address": [ - "127.0.0.1", - 63403 - ] - }, - "timestamp_ssl_setup": null, - "timestamp_end": null, - "clientcert": null, - "ssl_established": false - }, - "conntype": "http", - "version": [ - 0, - 11 - ], - "error": null, - "response": { - "code": 200, - "headers": [ - [ - "Server", - "nginx/1.1.19" - ], - [ - "Date", - "Sat, 13 Sep 2014 23:36:11 GMT" - ], - [ - "Content-Type", - "image/png" - ], - [ - "Content-Length", - "170108" - ], - [ - "Last-Modified", - "Wed, 26 Feb 2014 19:58:20 GMT" - ], - [ - "Connection", - "keep-alive" - ], - [ - "Accept-Ranges", - "bytes" - ] - ], - "timestamp_start": 1410651374.953, - "msg": "OK", - "timestamp_end": 1410651374.954, - "httpversion": [ - 1, - 1 - ] - } -}, -{ - "request": { - "timestamp_end": 1410651376.078, - "timestamp_start": 1410651376.075, - "form_in": "absolute", - "headers": [ - [ - "Host", - "mitmproxy.org" - ], - [ - "User-Agent", - "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" - ], - [ - "Accept", - "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" - ], - [ - "Accept-Language", - "de,en-US;q=0.7,en;q=0.3" - ], - [ - "Accept-Encoding", - "gzip, deflate" - ], - [ - "Cookie", - "__utma=30234659.1711188806.1410651375.1410651375.1410651375.1; __utmb=30234659.1.10.1410651375; __utmc=30234659; __utmz=30234659.1410651375.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)" - ], - [ - "Connection", - "keep-alive" - ] - ], - "host": "mitmproxy.org", - "form_out": "relative", - "path": "/favicon.ico", - "method": "GET", - "scheme": "http", - "port": 80, - "httpversion": [ - 1, - 1 - ] - }, - "server_conn": { - "timestamp_tcp_setup": 1410651374.189, - "state": [], - "timestamp_ssl_setup": null, - "sni": null, - "timestamp_start": 1410651373.985, - "address": { - "use_ipv6": false, - "address": [ - "mitmproxy.org", - 80 - ] - }, - "timestamp_end": null, - "source_address": { - "use_ipv6": false, - "address": [ - "192.168.1.117", - 63404 - ] - }, - "ssl_established": false - }, - "client_conn": { - "timestamp_start": 1410651373.958, - "address": { - "use_ipv6": false, - "address": [ - "127.0.0.1", - 63403 - ] - }, - "timestamp_ssl_setup": null, - "timestamp_end": null, - "clientcert": null, - "ssl_established": false - }, - "conntype": "http", - "version": [ - 0, - 11 - ], - "error": null, - "response": { - "code": 404, - "headers": [ - [ - "Server", - "nginx/1.1.19" - ], - [ - "Date", - "Sat, 13 Sep 2014 23:36:12 GMT" - ], - [ - "Content-Type", - "text/html" - ], - [ - "Content-Length", - "169" - ], - [ - "Connection", - "keep-alive" - ] - ], - "timestamp_start": 1410651376.254, - "msg": "Not Found", - "timestamp_end": 1410651376.255, - "httpversion": [ - 1, - 1 - ] - } -}, -{ - "request": { - "timestamp_end": 1410651376.282, - "timestamp_start": 1410651376.279, - "form_in": "absolute", - "headers": [ - [ - "Host", - "mitmproxy.org" - ], - [ - "User-Agent", - "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0" - ], - [ - "Accept", - "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" - ], - [ - "Accept-Language", - "de,en-US;q=0.7,en;q=0.3" - ], - [ - "Accept-Encoding", - "gzip, deflate" - ], - [ - "Cookie", - "__utma=30234659.1711188806.1410651375.1410651375.1410651375.1; __utmb=30234659.1.10.1410651375; __utmc=30234659; __utmz=30234659.1410651375.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)" - ], - [ - "Connection", - "keep-alive" - ] - ], - "host": "mitmproxy.org", - "form_out": "relative", - "path": "/favicon.ico", - "method": "GET", - "scheme": "http", - "port": 80, - "httpversion": [ - 1, - 1 - ] - }, - "server_conn": { - "timestamp_tcp_setup": 1410651374.189, - "state": [], - "timestamp_ssl_setup": null, - "sni": null, - "timestamp_start": 1410651373.985, - "address": { - "use_ipv6": false, - "address": [ - "mitmproxy.org", - 80 - ] - }, - "timestamp_end": null, - "source_address": { - "use_ipv6": false, - "address": [ - "192.168.1.117", - 63404 - ] - }, - "ssl_established": false - }, - "client_conn": { - "timestamp_start": 1410651373.958, - "address": { - "use_ipv6": false, - "address": [ - "127.0.0.1", - 63403 - ] - }, - "timestamp_ssl_setup": null, - "timestamp_end": null, - "clientcert": null, - "ssl_established": false - }, - "conntype": "http", - "version": [ - 0, - 11 - ], - "error": null, - "response": { - "code": 404, - "headers": [ - [ - "Server", - "nginx/1.1.19" - ], - [ - "Date", - "Sat, 13 Sep 2014 23:36:12 GMT" - ], - [ - "Content-Type", - "text/html" - ], - [ - "Content-Length", - "169" - ], - [ - "Connection", - "keep-alive" - ] - ], - "timestamp_start": 1410651376.461, - "msg": "Not Found", - "timestamp_end": 1410651376.462, - "httpversion": [ - 1, - 1 - ] - } -}]
\ No newline at end of file diff --git a/web/src/js/actions.js b/web/src/js/actions.js index 9211403f..2c4183e4 100644 --- a/web/src/js/actions.js +++ b/web/src/js/actions.js @@ -1,37 +1,64 @@ var ActionTypes = { - //Settings - UPDATE_SETTINGS: "update_settings", + // Connection + CONNECTION_OPEN: "connection_open", + CONNECTION_CLOSE: "connection_close", + CONNECTION_ERROR: "connection_error", - //EventLog - ADD_EVENT: "add_event", + // Stores + SETTINGS_STORE: "settings", + EVENT_STORE: "events", + FLOW_STORE: "flows", +}; - //Flow - ADD_FLOW: "add_flow", - UPDATE_FLOW: "update_flow", +var StoreCmds = { + ADD: "add", + UPDATE: "update", + REMOVE: "remove", + RESET: "reset" +}; + +var ConnectionActions = { + open: function () { + AppDispatcher.dispatchViewAction({ + type: ActionTypes.CONNECTION_OPEN + }); + }, + close: function () { + AppDispatcher.dispatchViewAction({ + type: ActionTypes.CONNECTION_CLOSE + }); + }, + error: function () { + AppDispatcher.dispatchViewAction({ + type: ActionTypes.CONNECTION_ERROR + }); + } }; var SettingsActions = { update: function (settings) { - settings = _.merge({}, SettingsStore.getAll(), settings); + //TODO: Update server. //Facebook Flux: We do an optimistic update on the client already. AppDispatcher.dispatchViewAction({ - type: ActionTypes.UPDATE_SETTINGS, - settings: settings + type: ActionTypes.SETTINGS_STORE, + cmd: StoreCmds.UPDATE, + data: settings }); } }; -var event_id = 0; +var EventLogActions_event_id = 0; var EventLogActions = { - add_event: function(message){ + add_event: function (message) { AppDispatcher.dispatchViewAction({ - type: ActionTypes.ADD_EVENT, + type: ActionTypes.EVENT_STORE, + cmd: StoreCmds.ADD, data: { message: message, level: "web", - id: "viewAction-"+event_id++ + id: "viewAction-" + EventLogActions_event_id++ } }); } diff --git a/web/src/js/app.js b/web/src/js/app.js index 736072dc..5146cb46 100644 --- a/web/src/js/app.js +++ b/web/src/js/app.js @@ -1,4 +1,7 @@ $(function () { - Connection.init(); - app = React.renderComponent(ProxyApp, document.body); + window.ws = new Connection("/updates"); + + ReactRouter.run(routes, function (Handler) { + React.render(<Handler/>, document.body); + }); });
\ No newline at end of file diff --git a/web/src/js/components/eventlog.jsx.js b/web/src/js/components/eventlog.jsx.js index 08a6dfb4..7ef369f8 100644 --- a/web/src/js/components/eventlog.jsx.js +++ b/web/src/js/components/eventlog.jsx.js @@ -1,10 +1,8 @@ -/** @jsx React.DOM */ - var LogMessage = React.createClass({ - render: function(){ + render: function () { var entry = this.props.entry; var indicator; - switch(entry.level){ + switch (entry.level) { case "web": indicator = <i className="fa fa-fw fa-html5"></i>; break; @@ -20,47 +18,79 @@ var LogMessage = React.createClass({ </div> ); }, - shouldComponentUpdate: function(){ + shouldComponentUpdate: function () { return false; // log entries are immutable. } }); var EventLogContents = React.createClass({ - mixins:[AutoScrollMixin], + mixins: [AutoScrollMixin, VirtualScrollMixin], getInitialState: function () { return { log: [] }; }, - componentDidMount: function () { - this.log = EventLogStore.getView(); - this.log.addListener("change", this.onEventLogChange); + componentWillMount: function () { + this.openView(this.props.eventStore); }, componentWillUnmount: function () { - this.log.removeListener("change", this.onEventLogChange); - this.log.close(); + this.closeView(); + }, + openView: function (store) { + var view = new StoreView(store, function (entry) { + return this.props.filter[entry.level]; + }.bind(this)); + this.setState({ + view: view + }); + + view.addListener("add recalculate", this.onEventLogChange); + }, + closeView: function () { + this.state.view.close(); }, onEventLogChange: function () { this.setState({ - log: this.log.getAll() + log: this.state.view.list }); }, + componentWillReceiveProps: function (nextProps) { + if (nextProps.filter !== this.props.filter) { + this.props.filter = nextProps.filter; // Dirty: Make sure that view filter sees the update. + this.state.view.recalculate(this.props.eventStore.list); + } + if (nextProps.eventStore !== this.props.eventStore) { + this.closeView(); + this.openView(nextProps.eventStore); + } + }, + getDefaultProps: function () { + return { + rowHeight: 45, + rowHeightMin: 15, + placeholderTagName: "div" + }; + }, + renderRow: function (elem) { + return <LogMessage key={elem.id} entry={elem}/>; + }, render: function () { - var messages = this.state.log.map(function(row) { - if(!this.props.filter[row.level]){ - return null; - } - return <LogMessage key={row.id} entry={row}/>; - }.bind(this)); - return <pre>{messages}</pre>; + var rows = this.renderRows(this.state.log); + + return <pre onScroll={this.onScroll}> + { this.getPlaceholderTop(this.state.log.length) } + {rows} + { this.getPlaceholderBottom(this.state.log.length) } + </pre>; } }); var ToggleFilter = React.createClass({ - toggle: function(){ + toggle: function (e) { + e.preventDefault(); return this.props.toggleLevel(this.props.name); }, - render: function(){ + render: function () { var className = "label "; if (this.props.active) { className += "label-primary"; @@ -75,11 +105,11 @@ var ToggleFilter = React.createClass({ {this.props.name} </a> ); - } + } }); var EventLog = React.createClass({ - getInitialState: function(){ + getInitialState: function () { return { filter: { "debug": false, @@ -93,11 +123,10 @@ var EventLog = React.createClass({ showEventLog: false }); }, - toggleLevel: function(level){ - var filter = this.state.filter; + toggleLevel: function (level) { + var filter = _.extend({}, this.state.filter); filter[level] = !filter[level]; this.setState({filter: filter}); - return false; }, render: function () { return ( @@ -112,7 +141,7 @@ var EventLog = React.createClass({ </div> </div> - <EventLogContents filter={this.state.filter}/> + <EventLogContents filter={this.state.filter} eventStore={this.props.eventStore}/> </div> ); } diff --git a/web/src/js/components/flowdetail.jsx.js b/web/src/js/components/flowdetail.jsx.js index 3ba025a9..6d46cd2e 100644 --- a/web/src/js/components/flowdetail.jsx.js +++ b/web/src/js/components/flowdetail.jsx.js @@ -1,34 +1,32 @@ -/** @jsx React.DOM */ - var FlowDetailNav = React.createClass({ - render: function(){ + render: function () { - var items = this.props.tabs.map(function(e){ + var items = this.props.tabs.map(function (e) { var str = e.charAt(0).toUpperCase() + e.slice(1); var className = this.props.active === e ? "active" : ""; - var onClick = function(){ + var onClick = function (event) { this.props.selectTab(e); - return false; + event.preventDefault(); }.bind(this); return <a key={e} - href="#" - className={className} - onClick={onClick}>{str}</a>; + href="#" + className={className} + onClick={onClick}>{str}</a>; }.bind(this)); return ( <nav ref="head" className="nav-tabs nav-tabs-sm"> {items} </nav> ); - } + } }); var Headers = React.createClass({ - render: function(){ - var rows = this.props.message.headers.map(function(header, i){ + render: function () { + var rows = this.props.message.headers.map(function (header, i) { return ( <tr key={i}> - <td className="header-name">{header[0]+":"}</td> + <td className="header-name">{header[0] + ":"}</td> <td className="header-value">{header[1]}</td> </tr> ); @@ -44,16 +42,16 @@ var Headers = React.createClass({ }); var FlowDetailRequest = React.createClass({ - render: function(){ + render: function () { var flow = this.props.flow; var first_line = [ - flow.request.method, - RequestUtils.pretty_url(flow.request), - "HTTP/"+ flow.response.httpversion.join(".") - ].join(" "); + flow.request.method, + RequestUtils.pretty_url(flow.request), + "HTTP/" + flow.request.httpversion.join(".") + ].join(" "); var content = null; - if(flow.request.contentLength > 0){ - content = "Request Content Size: "+ formatSize(flow.request.contentLength); + if (flow.request.contentLength > 0) { + content = "Request Content Size: " + formatSize(flow.request.contentLength); } else { content = <div className="alert alert-info">No Content</div>; } @@ -72,16 +70,16 @@ var FlowDetailRequest = React.createClass({ }); var FlowDetailResponse = React.createClass({ - render: function(){ + render: function () { var flow = this.props.flow; var first_line = [ - "HTTP/"+ flow.response.httpversion.join("."), - flow.response.code, - flow.response.msg - ].join(" "); + "HTTP/" + flow.response.httpversion.join("."), + flow.response.code, + flow.response.msg + ].join(" "); var content = null; - if(flow.response.contentLength > 0){ - content = "Response Content Size: "+ formatSize(flow.response.contentLength); + if (flow.response.contentLength > 0) { + content = "Response Content Size: " + formatSize(flow.response.contentLength); } else { content = <div className="alert alert-info">No Content</div>; } @@ -99,43 +97,67 @@ var FlowDetailResponse = React.createClass({ } }); +var FlowDetailError = React.createClass({ + render: function () { + var flow = this.props.flow; + return ( + <section> + <div className="alert alert-warning"> + {flow.error.msg} + <div><small>{ formatTimeStamp(flow.error.timestamp) }</small></div> + </div> + </section> + ); + } +}); + var TimeStamp = React.createClass({ - render: function() { + render: function () { - if(!this.props.t){ + if (!this.props.t) { //should be return null, but that triggers a React bug. return <tr></tr>; } - var ts = (new Date(this.props.t * 1000)).toISOString(); - ts = ts.replace("T", " ").replace("Z",""); + var ts = formatTimeStamp(this.props.t); var delta; - if(this.props.deltaTo){ - delta = formatTimeDelta(1000 * (this.props.t-this.props.deltaTo)); + if (this.props.deltaTo) { + delta = formatTimeDelta(1000 * (this.props.t - this.props.deltaTo)); delta = <span className="text-muted">{"(" + delta + ")"}</span>; } else { delta = null; } - return <tr><td>{this.props.title + ":"}</td><td>{ts} {delta}</td></tr>; + return <tr> + <td>{this.props.title + ":"}</td> + <td>{ts} {delta}</td> + </tr>; } }); var ConnectionInfo = React.createClass({ - render: function() { + render: function () { var conn = this.props.conn; var address = conn.address.address.join(":"); var sni = <tr key="sni"></tr>; //should be null, but that triggers a React bug. - if(conn.sni){ - sni = <tr key="sni"><td><abbr title="TLS Server Name Indication">TLS SNI:</abbr></td><td>{conn.sni}</td></tr>; + if (conn.sni) { + sni = <tr key="sni"> + <td> + <abbr title="TLS Server Name Indication">TLS SNI:</abbr> + </td> + <td>{conn.sni}</td> + </tr>; } return ( <table className="connection-table"> <tbody> - <tr key="address"><td>Address:</td><td>{address}</td></tr> + <tr key="address"> + <td>Address:</td> + <td>{address}</td> + </tr> {sni} </tbody> </table> @@ -144,7 +166,7 @@ var ConnectionInfo = React.createClass({ }); var CertificateInfo = React.createClass({ - render: function(){ + render: function () { //TODO: We should fetch human-readable certificate representation // from the server var flow = this.props.flow; @@ -165,7 +187,7 @@ var CertificateInfo = React.createClass({ }); var Timing = React.createClass({ - render: function(){ + render: function () { var flow = this.props.flow; var sc = flow.server_conn; var cc = flow.client_conn; @@ -218,82 +240,112 @@ var Timing = React.createClass({ } //Add unique key for each row. - timestamps.forEach(function(e){ + timestamps.forEach(function (e) { e.key = e.title; }); timestamps = _.sortBy(timestamps, 't'); - var rows = timestamps.map(function(e){ - return TimeStamp(e); + var rows = timestamps.map(function (e) { + return <TimeStamp {...e}/>; }); return ( <div> - <h4>Timing</h4> - <table className="timing-table"> - <tbody> + <h4>Timing</h4> + <table className="timing-table"> + <tbody> {rows} - </tbody> - </table> + </tbody> + </table> </div> ); } }); var FlowDetailConnectionInfo = React.createClass({ - render: function(){ + render: function () { var flow = this.props.flow; var client_conn = flow.client_conn; var server_conn = flow.server_conn; return ( <section> - <h4>Client Connection</h4> - <ConnectionInfo conn={client_conn}/> + <h4>Client Connection</h4> + <ConnectionInfo conn={client_conn}/> - <h4>Server Connection</h4> - <ConnectionInfo conn={server_conn}/> + <h4>Server Connection</h4> + <ConnectionInfo conn={server_conn}/> - <CertificateInfo flow={flow}/> + <CertificateInfo flow={flow}/> - <Timing flow={flow}/> + <Timing flow={flow}/> </section> ); } }); -var tabs = { +var allTabs = { request: FlowDetailRequest, response: FlowDetailResponse, + error: FlowDetailError, details: FlowDetailConnectionInfo }; var FlowDetail = React.createClass({ - getDefaultProps: function(){ - return { - tabs: ["request","response", "details"] - }; + mixins: [StickyHeadMixin, ReactRouter.Navigation, ReactRouter.State], + getTabs: function (flow) { + var tabs = []; + ["request", "response", "error"].forEach(function (e) { + if (flow[e]) { + tabs.push(e); + } + }); + tabs.push("details"); + return tabs; }, - mixins: [StickyHeadMixin], - nextTab: function(i) { - var currentIndex = this.props.tabs.indexOf(this.props.active); + nextTab: function (i) { + var tabs = this.getTabs(this.props.flow); + var currentIndex = tabs.indexOf(this.getParams().detailTab); // JS modulo operator doesn't correct negative numbers, make sure that we are positive. - var nextIndex = (currentIndex + i + this.props.tabs.length) % this.props.tabs.length; - this.props.selectTab(this.props.tabs[nextIndex]); + var nextIndex = (currentIndex + i + tabs.length) % tabs.length; + this.selectTab(tabs[nextIndex]); }, - render: function(){ - var flow = JSON.stringify(this.props.flow, null, 2); - var Tab = tabs[this.props.active]; + selectTab: function (panel) { + this.replaceWith( + "flow", + { + flowId: this.getParams().flowId, + detailTab: panel + } + ); + }, + render: function () { + var flow = this.props.flow; + var tabs = this.getTabs(flow); + var active = this.getParams().detailTab; + + if (!_.contains(tabs, active)) { + if (active === "response" && flow.error) { + active = "error"; + } else if (active === "error" && flow.response) { + active = "response"; + } else { + active = tabs[0]; + } + this.selectTab(active); + } + + var Tab = allTabs[active]; return ( <div className="flow-detail" onScroll={this.adjustHead}> <FlowDetailNav ref="head" - tabs={this.props.tabs} - active={this.props.active} - selectTab={this.props.selectTab}/> - <Tab flow={this.props.flow}/> + tabs={tabs} + active={active} + selectTab={this.selectTab}/> + <Tab flow={flow}/> </div> - ); - } + ); + } });
\ No newline at end of file diff --git a/web/src/js/components/flowtable-columns.jsx.js b/web/src/js/components/flowtable-columns.jsx.js index b7db71b7..1aa256c4 100644 --- a/web/src/js/components/flowtable-columns.jsx.js +++ b/web/src/js/components/flowtable-columns.jsx.js @@ -1,17 +1,14 @@ -/** @jsx React.DOM */ - - var TLSColumn = React.createClass({ statics: { - renderTitle: function(){ + renderTitle: function () { return <th key="tls" className="col-tls"></th>; } }, - render: function(){ + render: function () { var flow = this.props.flow; var ssl = (flow.request.scheme == "https"); var classes; - if(ssl){ + if (ssl) { classes = "col-tls col-tls-https"; } else { classes = "col-tls col-tls-http"; @@ -23,23 +20,23 @@ var TLSColumn = React.createClass({ var IconColumn = React.createClass({ statics: { - renderTitle: function(){ + renderTitle: function () { return <th key="icon" className="col-icon"></th>; } }, - render: function(){ + render: function () { var flow = this.props.flow; var icon; - if(flow.response){ + if (flow.response) { var contentType = ResponseUtils.getContentType(flow.response); //TODO: We should assign a type to the flow somewhere else. - if(flow.response.code == 304) { + if (flow.response.code == 304) { icon = "resource-icon-not-modified"; - } else if(300 <= flow.response.code && flow.response.code < 400) { + } else if (300 <= flow.response.code && flow.response.code < 400) { icon = "resource-icon-redirect"; - } else if(contentType && contentType.indexOf("image") >= 0) { + } else if (contentType && contentType.indexOf("image") >= 0) { icon = "resource-icon-image"; } else if (contentType && contentType.indexOf("javascript") >= 0) { icon = "resource-icon-js"; @@ -49,23 +46,25 @@ var IconColumn = React.createClass({ icon = "resource-icon-document"; } } - if(!icon){ + if (!icon) { icon = "resource-icon-plain"; } icon += " resource-icon"; - return <td className="col-icon"><div className={icon}></div></td>; + return <td className="col-icon"> + <div className={icon}></div> + </td>; } }); var PathColumn = React.createClass({ statics: { - renderTitle: function(){ + renderTitle: function () { return <th key="path" className="col-path">Path</th>; } }, - render: function(){ + render: function () { var flow = this.props.flow; return <td className="col-path">{flow.request.scheme + "://" + flow.request.host + flow.request.path}</td>; } @@ -74,11 +73,11 @@ var PathColumn = React.createClass({ var MethodColumn = React.createClass({ statics: { - renderTitle: function(){ + renderTitle: function () { return <th key="method" className="col-method">Method</th>; } }, - render: function(){ + render: function () { var flow = this.props.flow; return <td className="col-method">{flow.request.method}</td>; } @@ -87,14 +86,14 @@ var MethodColumn = React.createClass({ var StatusColumn = React.createClass({ statics: { - renderTitle: function(){ + renderTitle: function () { return <th key="status" className="col-status">Status</th>; } }, - render: function(){ + render: function () { var flow = this.props.flow; var status; - if(flow.response){ + if (flow.response) { status = flow.response.code; } else { status = null; @@ -106,15 +105,15 @@ var StatusColumn = React.createClass({ var SizeColumn = React.createClass({ statics: { - renderTitle: function(){ + renderTitle: function () { return <th key="size" className="col-size">Size</th>; } }, - render: function(){ + render: function () { var flow = this.props.flow; var total = flow.request.contentLength; - if(flow.response){ + if (flow.response) { total += flow.response.contentLength || 0; } var size = formatSize(total); @@ -125,14 +124,14 @@ var SizeColumn = React.createClass({ var TimeColumn = React.createClass({ statics: { - renderTitle: function(){ + renderTitle: function () { return <th key="time" className="col-time">Time</th>; } }, - render: function(){ + render: function () { var flow = this.props.flow; var time; - if(flow.response){ + if (flow.response) { time = formatTimeDelta(1000 * (flow.response.timestamp_end - flow.request.timestamp_start)); } else { time = "..."; diff --git a/web/src/js/components/flowtable.jsx.js b/web/src/js/components/flowtable.jsx.js index fc4d8fbc..4b72dd29 100644 --- a/web/src/js/components/flowtable.jsx.js +++ b/web/src/js/components/flowtable.jsx.js @@ -1,13 +1,11 @@ -/** @jsx React.DOM */ - var FlowRow = React.createClass({ - render: function(){ + render: function () { var flow = this.props.flow; - var columns = this.props.columns.map(function(column){ - return <column key={column.displayName} flow={flow}/>; + var columns = this.props.columns.map(function (Column) { + return <Column key={Column.displayName} flow={flow}/>; }.bind(this)); var className = ""; - if(this.props.selected){ + if (this.props.selected) { className += "selected"; } return ( @@ -15,80 +13,97 @@ var FlowRow = React.createClass({ {columns} </tr>); }, - shouldComponentUpdate: function(nextProps){ - var isEqual = ( - this.props.columns.length === nextProps.columns.length && - this.props.selected === nextProps.selected && - this.props.flow.response === nextProps.flow.response); - return !isEqual; + shouldComponentUpdate: function (nextProps) { + return true; + // Further optimization could be done here + // by calling forceUpdate on flow updates, selection changes and column changes. + //return ( + //(this.props.columns.length !== nextProps.columns.length) || + //(this.props.selected !== nextProps.selected) + //); } }); var FlowTableHead = React.createClass({ - render: function(){ - var columns = this.props.columns.map(function(column){ + render: function () { + var columns = this.props.columns.map(function (column) { return column.renderTitle(); }.bind(this)); - return <thead><tr>{columns}</tr></thead>; + return <thead> + <tr>{columns}</tr> + </thead>; } }); -var FlowTableBody = React.createClass({ - render: function(){ - var rows = this.props.flows.map(function(flow){ - var selected = (flow == this.props.selected); - return <FlowRow key={flow.id} - ref={flow.id} - flow={flow} - columns={this.props.columns} - selected={selected} - selectFlow={this.props.selectFlow} - />; - }.bind(this)); - return <tbody>{rows}</tbody>; - } -}); +var ROW_HEIGHT = 32; var FlowTable = React.createClass({ - mixins: [StickyHeadMixin, AutoScrollMixin], + mixins: [StickyHeadMixin, AutoScrollMixin, VirtualScrollMixin], getInitialState: function () { return { columns: all_columns }; }, - scrollIntoView: function(flow){ - // Now comes the fun part: Scroll the flow into the view. - var viewport = this.getDOMNode(); - var flowNode = this.refs.body.refs[flow.id].getDOMNode(); - var viewport_top = viewport.scrollTop; - var viewport_bottom = viewport_top + viewport.offsetHeight; - var flowNode_top = flowNode.offsetTop; - var flowNode_bottom = flowNode_top + flowNode.offsetHeight; - - // Account for pinned thead by pretending that the flowNode starts - // -thead_height pixel earlier. - flowNode_top -= this.refs.body.getDOMNode().offsetTop; - - if(flowNode_top < viewport_top){ - viewport.scrollTop = flowNode_top; - } else if(flowNode_bottom > viewport_bottom) { - viewport.scrollTop = flowNode_bottom - viewport.offsetHeight; + componentWillMount: function () { + if (this.props.view) { + this.props.view.addListener("add update remove recalculate", this.onChange); + } + }, + componentWillReceiveProps: function (nextProps) { + if (nextProps.view !== this.props.view) { + if (this.props.view) { + this.props.view.removeListener("add update remove recalculate"); + } + nextProps.view.addListener("add update remove recalculate", this.onChange); } }, + getDefaultProps: function () { + return { + rowHeight: ROW_HEIGHT + }; + }, + onScrollFlowTable: function () { + this.adjustHead(); + this.onScroll(); + }, + onChange: function () { + this.forceUpdate(); + }, + scrollIntoView: function (flow) { + this.scrollRowIntoView( + this.props.view.index(flow), + this.refs.body.getDOMNode().offsetTop + ); + }, + renderRow: function (flow) { + var selected = (flow === this.props.selected); + return <FlowRow key={flow.id} + ref={flow.id} + flow={flow} + columns={this.state.columns} + selected={selected} + selectFlow={this.props.selectFlow} + />; + }, render: function () { + //console.log("render flowtable", this.state.start, this.state.stop, this.props.selected); + var flows = this.props.view ? this.props.view.list : []; + + var rows = this.renderRows(flows); + return ( - <div className="flow-table" onScroll={this.adjustHead}> + <div className="flow-table" onScroll={this.onScrollFlowTable}> <table> <FlowTableHead ref="head" - columns={this.state.columns}/> - <FlowTableBody ref="body" - flows={this.props.flows} - selected={this.props.selected} - selectFlow={this.props.selectFlow} - columns={this.state.columns}/> + columns={this.state.columns}/> + <tbody ref="body"> + { this.getPlaceholderTop(flows.length) } + {rows} + { this.getPlaceholderBottom(flows.length) } + </tbody> </table> </div> - ); + ); } }); diff --git a/web/src/js/components/footer.jsx.js b/web/src/js/components/footer.jsx.js index 9bcbbc2a..73fadef2 100644 --- a/web/src/js/components/footer.jsx.js +++ b/web/src/js/components/footer.jsx.js @@ -1,5 +1,3 @@ -/** @jsx React.DOM */ - var Footer = React.createClass({ render: function () { var mode = this.props.settings.mode; @@ -7,6 +5,6 @@ var Footer = React.createClass({ <footer> {mode != "regular" ? <span className="label label-success">{mode} mode</span> : null} </footer> - ); + ); } }); diff --git a/web/src/js/components/header.jsx.js b/web/src/js/components/header.jsx.js index 994bc759..a23afa9b 100644 --- a/web/src/js/components/header.jsx.js +++ b/web/src/js/components/header.jsx.js @@ -1,5 +1,3 @@ -/** @jsx React.DOM */ - var MainMenu = React.createClass({ statics: { title: "Traffic", @@ -10,14 +8,23 @@ var MainMenu = React.createClass({ showEventLog: !this.props.settings.showEventLog }); }, + clearFlows: function () { + $.post("/flows/clear"); + }, render: function () { return ( <div> <button className={"btn " + (this.props.settings.showEventLog ? "btn-primary" : "btn-default")} onClick={this.toggleEventLog}> - <i className="fa fa-database"></i> Display Event Log + <i className="fa fa-database"></i> + Display Event Log + </button> + + <button className="btn btn-default" onClick={this.clearFlows}> + <i className="fa fa-eraser"></i> + Clear Flows </button> </div> - ); + ); } }); @@ -43,53 +50,125 @@ var ReportsMenu = React.createClass({ } }); +var FileMenu = React.createClass({ + getInitialState: function () { + return { + showFileMenu: false + }; + }, + handleFileClick: function (e) { + e.preventDefault(); + if (!this.state.showFileMenu) { + var close = function () { + this.setState({showFileMenu: false}); + document.removeEventListener("click", close); + }.bind(this); + document.addEventListener("click", close); + + this.setState({ + showFileMenu: true + }); + } + }, + handleNewClick: function(e){ + e.preventDefault(); + console.error("unimplemented: handleNewClick"); + }, + handleOpenClick: function(e){ + e.preventDefault(); + console.error("unimplemented: handleOpenClick"); + }, + handleSaveClick: function(e){ + e.preventDefault(); + console.error("unimplemented: handleSaveClick"); + }, + handleShutdownClick: function(e){ + e.preventDefault(); + console.error("unimplemented: handleShutdownClick"); + }, + render: function () { + var fileMenuClass = "dropdown pull-left" + (this.state.showFileMenu ? " open" : ""); + + return ( + <div className={fileMenuClass}> + <a href="#" className="special" onClick={this.handleFileClick}> File </a> + <ul className="dropdown-menu" role="menu"> + <li> + <a href="#" onClick={this.handleNewClick}> + <i className="fa fa-fw fa-file"></i> + New + </a> + </li> + <li> + <a href="#" onClick={this.handleOpenClick}> + <i className="fa fa-fw fa-folder-open"></i> + Open + </a> + </li> + <li> + <a href="#" onClick={this.handleSaveClick}> + <i className="fa fa-fw fa-save"></i> + Save + </a> + </li> + <li role="presentation" className="divider"></li> + <li> + <a href="#" onClick={this.handleShutdownClick}> + <i className="fa fa-fw fa-plug"></i> + Shutdown + </a> + </li> + </ul> + </div> + ); + } +}); + var header_entries = [MainMenu, ToolsMenu, ReportsMenu]; var Header = React.createClass({ + mixins: [ReactRouter.Navigation], getInitialState: function () { return { active: header_entries[0] }; }, - handleClick: function (active) { - ReactRouter.transitionTo(active.route); + handleClick: function (active, e) { + e.preventDefault(); + this.transitionTo(active.route); this.setState({active: active}); - return false; - }, - handleFileClick: function () { - console.log("File click"); }, render: function () { - var header = header_entries.map(function(entry, i){ + var header = header_entries.map(function (entry, i) { var classes = React.addons.classSet({ active: entry == this.state.active }); return ( - <a key={i} - href="#" - className={classes} - onClick={this.handleClick.bind(this, entry)} + <a key={i} + href="#" + className={classes} + onClick={this.handleClick.bind(this, entry)} > { entry.title} </a> - ); + ); }.bind(this)); - + return ( <header> <div className="title-bar"> mitmproxy { this.props.settings.version } </div> <nav className="nav-tabs nav-tabs-lg"> - <a href="#" className="special" onClick={this.handleFileClick}> File </a> + <FileMenu/> {header} </nav> <div className="menu"> <this.state.active settings={this.props.settings}/> </div> </header> - ); + ); } }); diff --git a/web/src/js/components/mainview.jsx.js b/web/src/js/components/mainview.jsx.js index 795b8136..17a024ee 100644 --- a/web/src/js/components/mainview.jsx.js +++ b/web/src/js/components/mainview.jsx.js @@ -1,65 +1,86 @@ -/** @jsx React.DOM */ - var MainView = React.createClass({ - getInitialState: function() { + mixins: [ReactRouter.Navigation, ReactRouter.State], + getInitialState: function () { return { - flows: [], + flows: [] }; }, - componentDidMount: function () { - this.flowStore = FlowStore.getView(); - this.flowStore.addListener("change",this.onFlowChange); - }, - componentWillUnmount: function () { - this.flowStore.removeListener("change",this.onFlowChange); - this.flowStore.close(); + componentWillReceiveProps: function (nextProps) { + if (nextProps.flowStore !== this.props.flowStore) { + this.closeView(); + this.openView(nextProps.flowStore); + } }, - onFlowChange: function () { + openView: function (store) { + var view = new StoreView(store); this.setState({ - flows: this.flowStore.getAll() + view: view }); + + view.addListener("recalculate", this.onRecalculate); + view.addListener("add update remove", this.onUpdate); }, - selectDetailTab: function(panel) { - ReactRouter.replaceWith( - "flow", - { - flowId: this.props.params.flowId, - detailTab: panel - } - ); + onRecalculate: function(){ + this.forceUpdate(); + var selected = this.getSelected(); + if(selected){ + this.refs.flowTable.scrollIntoView(selected); + } + }, + onUpdate: function (flow) { + if (flow.id === this.getParams().flowId) { + this.forceUpdate(); + } + }, + closeView: function () { + this.state.view.close(); + }, + componentWillMount: function () { + this.openView(this.props.flowStore); + }, + componentWillUnmount: function () { + this.closeView(); }, - selectFlow: function(flow) { - if(flow){ - ReactRouter.replaceWith( - "flow", + selectFlow: function (flow) { + if (flow) { + this.replaceWith( + "flow", { flowId: flow.id, - detailTab: this.props.params.detailTab || "request" + detailTab: this.getParams().detailTab || "request" } ); this.refs.flowTable.scrollIntoView(flow); } else { - ReactRouter.replaceWith("flows"); + this.replaceWith("flows"); } }, - selectFlowRelative: function(i){ + selectFlowRelative: function (shift) { + var flows = this.state.view.list; var index; - if(!this.props.params.flowId){ - if(i > 0){ - index = this.state.flows.length-1; + if (!this.getParams().flowId) { + if (shift > 0) { + index = flows.length - 1; } else { index = 0; } } else { - index = _.findIndex(this.state.flows, function(f){ - return f.id === this.props.params.flowId; - }.bind(this)); - index = Math.min(Math.max(0, index+i), this.state.flows.length-1); + var currFlowId = this.getParams().flowId; + var i = flows.length; + while (i--) { + if (flows[i].id === currFlowId) { + index = i; + break; + } + } + index = Math.min( + Math.max(0, index + shift), + flows.length - 1); } - this.selectFlow(this.state.flows[index]); + this.selectFlow(flows[index]); }, - onKeyDown: function(e){ - switch(e.keyCode){ + onKeyDown: function (e) { + switch (e.keyCode) { case Key.K: case Key.UP: this.selectFlowRelative(-1); @@ -80,14 +101,14 @@ var MainView = React.createClass({ break; case Key.H: case Key.LEFT: - if(this.refs.flowDetails){ + if (this.refs.flowDetails) { this.refs.flowDetails.nextTab(-1); } break; case Key.L: case Key.TAB: case Key.RIGHT: - if(this.refs.flowDetails){ + if (this.refs.flowDetails) { this.refs.flowDetails.nextTab(+1); } break; @@ -95,19 +116,20 @@ var MainView = React.createClass({ console.debug("keydown", e.keyCode); return; } - return false; + e.preventDefault(); + }, + getSelected: function(){ + return this.props.flowStore.get(this.getParams().flowId); }, - render: function() { - var selected = _.find(this.state.flows, { id: this.props.params.flowId }); + render: function () { + var selected = this.getSelected(); var details; - if(selected){ - details = ( - <FlowDetail ref="flowDetails" - flow={selected} - selectTab={this.selectDetailTab} - active={this.props.params.detailTab}/> - ); + if (selected) { + details = [ + <Splitter key="splitter"/>, + <FlowDetail key="flowDetails" ref="flowDetails" flow={selected}/> + ]; } else { details = null; } @@ -115,10 +137,9 @@ var MainView = React.createClass({ return ( <div className="main-view" onKeyDown={this.onKeyDown} tabIndex="0"> <FlowTable ref="flowTable" - flows={this.state.flows} - selectFlow={this.selectFlow} - selected={selected} /> - { details ? <Splitter/> : null } + view={this.state.view} + selectFlow={this.selectFlow} + selected={selected} /> {details} </div> ); diff --git a/web/src/js/components/proxyapp.jsx.js b/web/src/js/components/proxyapp.jsx.js index ff6e8da1..20162ad1 100644 --- a/web/src/js/components/proxyapp.jsx.js +++ b/web/src/js/components/proxyapp.jsx.js @@ -1,5 +1,3 @@ -/** @jsx React.DOM */ - //TODO: Move out of here, just a stub. var Reports = React.createClass({ render: function () { @@ -10,45 +8,67 @@ var Reports = React.createClass({ var ProxyAppMain = React.createClass({ getInitialState: function () { - return { settings: SettingsStore.getAll() }; + var eventStore = new EventLogStore(); + var flowStore = new FlowStore(); + var settings = new SettingsStore(); + + // Default Settings before fetch + _.extend(settings.dict,{ + showEventLog: true + }); + return { + settings: settings, + flowStore: flowStore, + eventStore: eventStore + }; }, componentDidMount: function () { - SettingsStore.addListener("change", this.onSettingsChange); + this.state.settings.addListener("recalculate", this.onSettingsChange); }, componentWillUnmount: function () { - SettingsStore.removeListener("change", this.onSettingsChange); + this.state.settings.removeListener("recalculate", this.onSettingsChange); }, - onSettingsChange: function () { - this.setState({settings: SettingsStore.getAll()}); + onSettingsChange: function(){ + this.setState({ + settings: this.state.settings + }); }, render: function () { + + var eventlog; + if (this.state.settings.dict.showEventLog) { + eventlog = [ + <Splitter key="splitter" axis="y"/>, + <EventLog key="eventlog" eventStore={this.state.eventStore}/> + ]; + } else { + eventlog = null; + } + return ( <div id="container"> - <Header settings={this.state.settings}/> - <this.props.activeRouteHandler settings={this.state.settings}/> - {this.state.settings.showEventLog ? <Splitter axis="y"/> : null} - {this.state.settings.showEventLog ? <EventLog/> : null} - <Footer settings={this.state.settings}/> + <Header settings={this.state.settings.dict}/> + <RouteHandler settings={this.state.settings.dict} flowStore={this.state.flowStore}/> + {eventlog} + <Footer settings={this.state.settings.dict}/> </div> - ); + ); } }); -var Routes = ReactRouter.Routes; var Route = ReactRouter.Route; +var RouteHandler = ReactRouter.RouteHandler; var Redirect = ReactRouter.Redirect; var DefaultRoute = ReactRouter.DefaultRoute; var NotFoundRoute = ReactRouter.NotFoundRoute; -var ProxyApp = ( - <Routes location="hash"> - <Route path="/" handler={ProxyAppMain}> - <Route name="flows" path="flows" handler={MainView}/> - <Route name="flow" path="flows/:flowId/:detailTab" handler={MainView}/> - <Route name="reports" handler={Reports}/> - <Redirect path="/" to="flows" /> - </Route> - </Routes> - );
\ No newline at end of file +var routes = ( + <Route path="/" handler={ProxyAppMain}> + <Route name="flows" path="flows" handler={MainView}/> + <Route name="flow" path="flows/:flowId/:detailTab" handler={MainView}/> + <Route name="reports" handler={Reports}/> + <Redirect path="/" to="flows" /> + </Route> +);
\ No newline at end of file diff --git a/web/src/js/components/utils.jsx.js b/web/src/js/components/utils.jsx.js index 91cb8458..81ba6b4d 100644 --- a/web/src/js/components/utils.jsx.js +++ b/web/src/js/components/utils.jsx.js @@ -1,5 +1,3 @@ -/** @jsx React.DOM */ - //React utils. For other utilities, see ../utils.js var Splitter = React.createClass({ @@ -8,85 +6,93 @@ var Splitter = React.createClass({ axis: "x" }; }, - getInitialState: function(){ + getInitialState: function () { return { applied: false, startX: false, startY: false }; }, - onMouseDown: function(e){ + onMouseDown: function (e) { this.setState({ startX: e.pageX, startY: e.pageY }); - window.addEventListener("mousemove",this.onMouseMove); - window.addEventListener("mouseup",this.onMouseUp); + window.addEventListener("mousemove", this.onMouseMove); + window.addEventListener("mouseup", this.onMouseUp); // Occasionally, only a dragEnd event is triggered, but no mouseUp. - window.addEventListener("dragend",this.onDragEnd); + window.addEventListener("dragend", this.onDragEnd); }, - onDragEnd: function(){ - this.getDOMNode().style.transform=""; - window.removeEventListener("dragend",this.onDragEnd); - window.removeEventListener("mouseup",this.onMouseUp); - window.removeEventListener("mousemove",this.onMouseMove); + onDragEnd: function () { + this.getDOMNode().style.transform = ""; + window.removeEventListener("dragend", this.onDragEnd); + window.removeEventListener("mouseup", this.onMouseUp); + window.removeEventListener("mousemove", this.onMouseMove); }, - onMouseUp: function(e){ + onMouseUp: function (e) { this.onDragEnd(); var node = this.getDOMNode(); var prev = node.previousElementSibling; var next = node.nextElementSibling; - var dX = e.pageX-this.state.startX; - var dY = e.pageY-this.state.startY; + var dX = e.pageX - this.state.startX; + var dY = e.pageY - this.state.startY; var flexBasis; - if(this.props.axis === "x"){ + if (this.props.axis === "x") { flexBasis = prev.offsetWidth + dX; } else { flexBasis = prev.offsetHeight + dY; } - prev.style.flex = "0 0 "+Math.max(0, flexBasis)+"px"; + prev.style.flex = "0 0 " + Math.max(0, flexBasis) + "px"; next.style.flex = "1 1 auto"; this.setState({ applied: true }); + this.onResize(); }, - onMouseMove: function(e){ + onMouseMove: function (e) { var dX = 0, dY = 0; - if(this.props.axis === "x"){ - dX = e.pageX-this.state.startX; + if (this.props.axis === "x") { + dX = e.pageX - this.state.startX; } else { - dY = e.pageY-this.state.startY; + dY = e.pageY - this.state.startY; } - this.getDOMNode().style.transform = "translate("+dX+"px,"+dY+"px)"; + this.getDOMNode().style.transform = "translate(" + dX + "px," + dY + "px)"; + }, + onResize: function () { + // Trigger a global resize event. This notifies components that employ virtual scrolling + // that their viewport may have changed. + window.setTimeout(function () { + window.dispatchEvent(new CustomEvent("resize")); + }, 1); }, - reset: function(willUnmount) { + reset: function (willUnmount) { if (!this.state.applied) { return; } var node = this.getDOMNode(); var prev = node.previousElementSibling; var next = node.nextElementSibling; - + prev.style.flex = ""; next.style.flex = ""; - if(!willUnmount){ + if (!willUnmount) { this.setState({ applied: false }); } - + this.onResize(); }, - componentWillUnmount: function(){ + componentWillUnmount: function () { this.reset(true); }, - render: function(){ + render: function () { var className = "splitter"; - if(this.props.axis === "x"){ + if (this.props.axis === "x") { className += " splitter-x"; } else { className += " splitter-y"; @@ -97,4 +103,21 @@ var Splitter = React.createClass({ </div> ); } +}); + +function getCookie(name) { + var r = document.cookie.match("\\b" + name + "=([^;]*)\\b"); + return r ? r[1] : undefined; +} +var xsrf = $.param({_xsrf: getCookie("_xsrf")}); + +//Tornado XSRF Protection. +$.ajaxPrefilter(function (options) { + if (options.type === "post" && options.url[0] === "/") { + if (options.data) { + options.data += ("&" + xsrf); + } else { + options.data = xsrf; + } + } });
\ No newline at end of file diff --git a/web/src/js/components/virtualscroll.jsx.js b/web/src/js/components/virtualscroll.jsx.js new file mode 100644 index 00000000..4f946cb4 --- /dev/null +++ b/web/src/js/components/virtualscroll.jsx.js @@ -0,0 +1,81 @@ +var VirtualScrollMixin = { + getInitialState: function () { + return { + start: 0, + stop: 0 + }; + }, + componentWillMount: function () { + if (!this.props.rowHeight) { + console.warn("VirtualScrollMixin: No rowHeight specified", this); + } + }, + getPlaceholderTop: function (total) { + var Tag = this.props.placeholderTagName || "tr"; + // When a large trunk of elements is removed from the button, start may be far off the viewport. + // To make this issue less severe, limit the top placeholder to the total number of rows. + var style = { + height: Math.min(this.state.start, total) * this.props.rowHeight + }; + var spacer = <Tag key="placeholder-top" style={style}></Tag>; + + if (this.state.start % 2 === 1) { + // fix even/odd rows + return [spacer, <Tag key="placeholder-top-2"></Tag>]; + } else { + return spacer; + } + }, + getPlaceholderBottom: function (total) { + var Tag = this.props.placeholderTagName || "tr"; + var style = { + height: Math.max(0, total - this.state.stop) * this.props.rowHeight + }; + return <Tag key="placeholder-bottom" style={style}></Tag>; + }, + componentDidMount: function () { + this.onScroll(); + window.addEventListener('resize', this.onScroll); + }, + componentWillUnmount: function(){ + window.removeEventListener('resize', this.onScroll); + }, + onScroll: function () { + var viewport = this.getDOMNode(); + var top = viewport.scrollTop; + var height = viewport.offsetHeight; + var start = Math.floor(top / this.props.rowHeight); + var stop = start + Math.ceil(height / (this.props.rowHeightMin || this.props.rowHeight)); + + this.setState({ + start: start, + stop: stop + }); + }, + renderRows: function (elems) { + var rows = []; + var max = Math.min(elems.length, this.state.stop); + + for (var i = this.state.start; i < max; i++) { + var elem = elems[i]; + rows.push(this.renderRow(elem)); + } + return rows; + }, + scrollRowIntoView: function (index, head_height) { + + var row_top = (index * this.props.rowHeight) + head_height; + var row_bottom = row_top + this.props.rowHeight; + + var viewport = this.getDOMNode(); + var viewport_top = viewport.scrollTop; + var viewport_bottom = viewport_top + viewport.offsetHeight; + + // Account for pinned thead + if (row_top - head_height < viewport_top) { + viewport.scrollTop = row_top - head_height; + } else if (row_bottom > viewport_bottom) { + viewport.scrollTop = row_bottom - viewport.offsetHeight; + } + }, +};
\ No newline at end of file diff --git a/web/src/js/connection.js b/web/src/js/connection.js index 3edbfc20..6ca353b3 100644 --- a/web/src/js/connection.js +++ b/web/src/js/connection.js @@ -1,33 +1,24 @@ -function _Connection(url) { - this.url = url; -} -_Connection.prototype.init = function () { - this.openWebSocketConnection(); -}; -_Connection.prototype.openWebSocketConnection = function () { - this.ws = new WebSocket(this.url.replace("http", "ws")); - var ws = this.ws; +function Connection(url) { - ws.onopen = this.onopen.bind(this); - ws.onmessage = this.onmessage.bind(this); - ws.onerror = this.onerror.bind(this); - ws.onclose = this.onclose.bind(this); -}; -_Connection.prototype.onopen = function (open) { - console.debug("onopen", this, arguments); -}; -_Connection.prototype.onmessage = function (message) { - //AppDispatcher.dispatchServerAction(...); - var m = JSON.parse(message.data); - AppDispatcher.dispatchServerAction(m); -}; -_Connection.prototype.onerror = function (error) { - EventLogActions.add_event("WebSocket Connection Error."); - console.debug("onerror", this, arguments); -}; -_Connection.prototype.onclose = function (close) { - EventLogActions.add_event("WebSocket Connection closed."); - console.debug("onclose", this, arguments); -}; + if (url[0] === "/") { + url = location.origin.replace("http", "ws") + url; + } -var Connection = new _Connection(location.origin + "/updates"); + var ws = new WebSocket(url); + ws.onopen = function () { + ConnectionActions.open(); + }; + ws.onmessage = function (message) { + var m = JSON.parse(message.data); + AppDispatcher.dispatchServerAction(m); + }; + ws.onerror = function () { + ConnectionActions.error(); + EventLogActions.add_event("WebSocket connection error."); + }; + ws.onclose = function () { + ConnectionActions.close(); + EventLogActions.add_event("WebSocket connection closed."); + }; + return ws; +}
\ No newline at end of file diff --git a/web/src/js/dispatcher.js b/web/src/js/dispatcher.js index 4fe23447..860ade9f 100644 --- a/web/src/js/dispatcher.js +++ b/web/src/js/dispatcher.js @@ -11,14 +11,14 @@ Dispatcher.prototype.register = function (callback) { this.callbacks.push(callback); }; Dispatcher.prototype.unregister = function (callback) { - var index = this.callbacks.indexOf(f); + var index = this.callbacks.indexOf(callback); if (index >= 0) { - this.callbacks.splice(this.callbacks.indexOf(f), 1); + this.callbacks.splice(index, 1); } }; Dispatcher.prototype.dispatch = function (payload) { console.debug("dispatch", payload); - for(var i = 0; i < this.callbacks.length; i++){ + for (var i = 0; i < this.callbacks.length; i++) { this.callbacks[i](payload); } }; diff --git a/web/src/js/filt/filt.pegjs b/web/src/js/filt/filt.pegjs new file mode 100644 index 00000000..06e2ecb3 --- /dev/null +++ b/web/src/js/filt/filt.pegjs @@ -0,0 +1,93 @@ +// PEG.js filter rules - see http://pegjs.majda.cz/online + +/* Explain Filter */ +{ + var or = function(first, second) { + return first + " or " + second; + }; + var and = function(first, second) { + return first + " and " + second; + }; + var not = function(expr) { + return "not " + expr; + }; + var binding = function(expr) { + return "(" + expr + ")"; + } + var assetFilter = "is asset"; + var trueFilter = true; + var falseFilter = false; + var bodyFilter = function(s) { + return "body ~= '" + s + "'"; + } + var urlFilter = function(s) { + return "url ~= '" + s + "'"; + } +} + +start "filter expression" + = __ orExpr:OrExpr __ { return orExpr; } + +ws "whitespace" = [ \t\n\r] +cc "control character" = [|&!()~"] +__ "optional whitespace" = ws* + +OrExpr + = first:AndExpr __ "|" __ second:OrExpr + { return or(first, second); } + / AndExpr + +AndExpr + = first:NotExpr __ "&" __ second:AndExpr + { return and(first, second); } + / first:NotExpr ws+ second:AndExpr + { return and(first, second); } + / NotExpr + +NotExpr + = "!" __ expr:NotExpr + { return not(expr); } + / BindingExpr + +BindingExpr + = "(" __ expr:OrExpr __ ")" + { return binding(orExpr); } + / Expr + +Expr + = NullaryExpr + / UnaryExpr + +NullaryExpr + = BooleanLiteral + / "~a" { return assetFilter; }; + +BooleanLiteral + = "true" { return trueFilter; } + / "false" { return falseFilter; } + +UnaryExpr + = "~b" ws+ s:StringLiteral { return bodyFilter(s); } + / s:StringLiteral { return urlFilter(s); } + +StringLiteral "string" + = '"' chars:DoubleStringChar* '"' { return chars.join(""); } + / "'" chars:SingleStringChar* "'" { return chars.join(""); } + / !cc chars:UnquotedStringChar+ { return chars.join(""); } + +DoubleStringChar + = !["\\] char:. { return char; } + / "\\" char:EscapeSequence { return char; } + +SingleStringChar + = !['\\] char:. { return char; } + / "\\" char:EscapeSequence { return char; } + +UnquotedStringChar + = !ws char:. { return char; } + +EscapeSequence + = ['"\\] + / "n" { return "\n"; } + / "r" { return "\r"; } + / "t" { return "\t"; }
\ No newline at end of file diff --git a/web/src/js/store/settingstore.js b/web/src/js/store/settingstore.js new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/web/src/js/store/settingstore.js diff --git a/web/src/js/store/store.js b/web/src/js/store/store.js new file mode 100644 index 00000000..0f94e496 --- /dev/null +++ b/web/src/js/store/store.js @@ -0,0 +1,164 @@ +function ListStore() { + EventEmitter.call(this); + this.reset(); +} +_.extend(ListStore.prototype, EventEmitter.prototype, { + add: function (elem) { + if (elem.id in this._pos_map) { + return; + } + this._pos_map[elem.id] = this.list.length; + this.list.push(elem); + this.emit("add", elem); + }, + update: function (elem) { + if (!(elem.id in this._pos_map)) { + return; + } + this.list[this._pos_map[elem.id]] = elem; + this.emit("update", elem); + }, + remove: function (elem_id) { + if (!(elem.id in this._pos_map)) { + return; + } + this.list.splice(this._pos_map[elem_id], 1); + this._build_map(); + this.emit("remove", elem_id); + }, + reset: function (elems) { + this.list = elems || []; + this._build_map(); + this.emit("recalculate", this.list); + }, + _build_map: function () { + this._pos_map = {}; + for (var i = 0; i < this.list.length; i++) { + var elem = this.list[i]; + this._pos_map[elem.id] = i; + } + }, + get: function (elem_id) { + return this.list[this._pos_map[elem_id]]; + }, + index: function (elem_id) { + return this._pos_map[elem_id]; + } +}); + + +function DictStore() { + EventEmitter.call(this); + this.reset(); +} +_.extend(DictStore.prototype, EventEmitter.prototype, { + update: function (dict) { + _.merge(this.dict, dict); + this.emit("recalculate", this.dict); + }, + reset: function (dict) { + this.dict = dict || {}; + this.emit("recalculate", this.dict); + } +}); + +function LiveStoreMixin(type) { + this.type = type; + + this._updates_before_fetch = undefined; + this._fetchxhr = false; + + this.handle = this.handle.bind(this); + AppDispatcher.register(this.handle); + + // Avoid double-fetch on startup. + if (!(window.ws && window.ws.readyState === WebSocket.CONNECTING)) { + this.fetch(); + } +} +_.extend(LiveStoreMixin.prototype, { + handle: function (event) { + if (event.type === ActionTypes.CONNECTION_OPEN) { + return this.fetch(); + } + if (event.type === this.type) { + if (event.cmd === StoreCmds.RESET) { + this.fetch(); + } else if (this._updates_before_fetch) { + console.log("defer update", event); + this._updates_before_fetch.push(event); + } else { + this[event.cmd](event.data); + } + } + }, + close: function () { + AppDispatcher.unregister(this.handle); + }, + fetch: function (data) { + console.log("fetch " + this.type); + if (this._fetchxhr) { + this._fetchxhr.abort(); + } + this._updates_before_fetch = []; // (JS: empty array is true) + if (data) { + this.handle_fetch(data); + } else { + this._fetchxhr = $.getJSON("/" + this.type) + .done(function (message) { + this.handle_fetch(message.data); + }.bind(this)) + .fail(function () { + EventLogActions.add_event("Could not fetch " + this.type); + }.bind(this)); + } + }, + handle_fetch: function (data) { + this._fetchxhr = false; + console.log(this.type + " fetched.", this._updates_before_fetch); + this.reset(data); + var updates = this._updates_before_fetch; + this._updates_before_fetch = false; + for (var i = 0; i < updates.length; i++) { + this.handle(updates[i]); + } + }, +}); + +function LiveListStore(type) { + ListStore.call(this); + LiveStoreMixin.call(this, type); +} +_.extend(LiveListStore.prototype, ListStore.prototype, LiveStoreMixin.prototype); + +function LiveDictStore(type) { + DictStore.call(this); + LiveStoreMixin.call(this, type); +} +_.extend(LiveDictStore.prototype, DictStore.prototype, LiveStoreMixin.prototype); + + +function FlowStore() { + return new LiveListStore(ActionTypes.FLOW_STORE); +} + +function SettingsStore() { + return new LiveDictStore(ActionTypes.SETTINGS_STORE); +} + +function EventLogStore() { + LiveListStore.call(this, ActionTypes.EVENT_STORE); +} +_.extend(EventLogStore.prototype, LiveListStore.prototype, { + fetch: function(){ + LiveListStore.prototype.fetch.apply(this, arguments); + + // Make sure to display updates even if fetching all events failed. + // This way, we can send "fetch failed" log messages to the log. + if(this._fetchxhr){ + this._fetchxhr.fail(function(){ + this.handle_fetch(null); + }.bind(this)); + } + } +});
\ No newline at end of file diff --git a/web/src/js/store/view.js b/web/src/js/store/view.js new file mode 100644 index 00000000..56bc4dbd --- /dev/null +++ b/web/src/js/store/view.js @@ -0,0 +1,99 @@ +function SortByStoreOrder(elem) { + return this.store.index(elem.id); +} + +var default_sort = SortByStoreOrder; +var default_filt = function(elem){ + return true; +}; + +function StoreView(store, filt, sortfun) { + EventEmitter.call(this); + filt = filt || default_filt; + sortfun = sortfun || default_sort; + + this.store = store; + + this.add = this.add.bind(this); + this.update = this.update.bind(this); + this.remove = this.remove.bind(this); + this.recalculate = this.recalculate.bind(this); + this.store.addListener("add", this.add); + this.store.addListener("update", this.update); + this.store.addListener("remove", this.remove); + this.store.addListener("recalculate", this.recalculate); + + this.recalculate(this.store.list, filt, sortfun); +} + +_.extend(StoreView.prototype, EventEmitter.prototype, { + close: function () { + this.store.removeListener("add", this.add); + this.store.removeListener("update", this.update); + this.store.removeListener("remove", this.remove); + this.store.removeListener("recalculate", this.recalculate); + }, + recalculate: function (elems, filt, sortfun) { + if (filt) { + this.filt = filt; + } + if (sortfun) { + this.sortfun = sortfun.bind(this); + } + + this.list = elems.filter(this.filt); + this.list.sort(function (a, b) { + return this.sortfun(a) - this.sortfun(b); + }.bind(this)); + this.emit("recalculate"); + }, + index: function (elem) { + return _.sortedIndex(this.list, elem, this.sortfun); + }, + add: function (elem) { + if (this.filt(elem)) { + var idx = this.index(elem); + if (idx === this.list.length) { //happens often, .push is way faster. + this.list.push(elem); + } else { + this.list.splice(idx, 0, elem); + } + this.emit("add", elem, idx); + } + }, + update: function (elem) { + var idx; + var i = this.list.length; + // Search from the back, we usually update the latest entries. + while (i--) { + if (this.list[i].id === elem.id) { + idx = i; + break; + } + } + + if (idx === -1) { //not contained in list + this.add(elem); + } else if (!this.filt(elem)) { + this.remove(elem.id); + } else { + if (this.sortfun(this.list[idx]) !== this.sortfun(elem)) { //sortpos has changed + this.remove(this.list[idx]); + this.add(elem); + } else { + this.list[idx] = elem; + this.emit("update", elem, idx); + } + } + }, + remove: function (elem_id) { + var idx = this.list.length; + while (idx--) { + if (this.list[idx].id === elem_id) { + this.list.splice(idx, 1); + this.emit("remove", elem_id, idx); + break; + } + } + } +});
\ No newline at end of file diff --git a/web/src/js/stores/base.js b/web/src/js/stores/base.js deleted file mode 100644 index 952fa847..00000000 --- a/web/src/js/stores/base.js +++ /dev/null @@ -1,25 +0,0 @@ -function EventEmitter() { - this.listeners = {}; -} -EventEmitter.prototype.emit = function (event) { - if (!(event in this.listeners)) { - return; - } - var args = Array.prototype.slice.call(arguments, 1); - this.listeners[event].forEach(function (listener) { - listener.apply(this, args); - }.bind(this)); -}; -EventEmitter.prototype.addListener = function (event, f) { - this.listeners[event] = this.listeners[event] || []; - this.listeners[event].push(f); -}; -EventEmitter.prototype.removeListener = function (event, f) { - if (!(event in this.listeners)) { - return false; - } - var index = this.listeners[event].indexOf(f); - if (index >= 0) { - this.listeners[event].splice(index, 1); - } -}; diff --git a/web/src/js/stores/eventlogstore.js b/web/src/js/stores/eventlogstore.js deleted file mode 100644 index e356959a..00000000 --- a/web/src/js/stores/eventlogstore.js +++ /dev/null @@ -1,99 +0,0 @@ -// -// We have an EventLogView and an EventLogStore: -// The basic architecture is that one can request views on the event log -// from the store, which returns a view object and then deals with getting the data required for the view. -// The view object is accessed by React components and distributes updates etc. -// -// See also: components/EventLog.react.js -function EventLogView(store, live) { - EventEmitter.call(this); - this._store = store; - this.live = live; - this.log = []; - - this.add = this.add.bind(this); - - if (live) { - this._store.addListener(ActionTypes.ADD_EVENT, this.add); - } -} -_.extend(EventLogView.prototype, EventEmitter.prototype, { - close: function () { - this._store.removeListener(ActionTypes.ADD_EVENT, this.add); - }, - getAll: function () { - return this.log; - }, - add: function (entry) { - this.log.push(entry); - if(this.log.length > 200){ - this.log.shift(); - } - this.emit("change"); - }, - add_bulk: function (messages) { - var log = messages; - var last_id = log[log.length - 1].id; - var to_add = _.filter(this.log, function (entry) { - return entry.id > last_id; - }); - this.log = log.concat(to_add); - this.emit("change"); - } -}); - - -function _EventLogStore() { - EventEmitter.call(this); -} -_.extend(_EventLogStore.prototype, EventEmitter.prototype, { - getView: function (since) { - var view = new EventLogView(this, !since); - return view; - /* - //TODO: Really do bulk retrieval of last messages. - window.setTimeout(function () { - view.add_bulk([ - { - id: 1, - message: "Hello World" - }, - { - id: 2, - message: "I was already transmitted as an event." - } - ]); - }, 100); - - var id = 2; - view.add({ - id: id++, - message: "I was already transmitted as an event." - }); - view.add({ - id: id++, - message: "I was only transmitted as an event before the bulk was added.." - }); - window.setInterval(function () { - view.add({ - id: id++, - message: "." - }); - }, 1000); - return view; - */ - }, - handle: function (action) { - switch (action.type) { - case ActionTypes.ADD_EVENT: - this.emit(ActionTypes.ADD_EVENT, action.data); - break; - default: - return; - } - } -}); - - -var EventLogStore = new _EventLogStore(); -AppDispatcher.register(EventLogStore.handle.bind(EventLogStore));
\ No newline at end of file diff --git a/web/src/js/stores/flowstore.js b/web/src/js/stores/flowstore.js deleted file mode 100644 index 7c0bddbd..00000000 --- a/web/src/js/stores/flowstore.js +++ /dev/null @@ -1,91 +0,0 @@ -function FlowView(store, live) { - EventEmitter.call(this); - this._store = store; - this.live = live; - this.flows = []; - - this.add = this.add.bind(this); - this.update = this.update.bind(this); - - if (live) { - this._store.addListener(ActionTypes.ADD_FLOW, this.add); - this._store.addListener(ActionTypes.UPDATE_FLOW, this.update); - } -} - -_.extend(FlowView.prototype, EventEmitter.prototype, { - close: function () { - this._store.removeListener(ActionTypes.ADD_FLOW, this.add); - this._store.removeListener(ActionTypes.UPDATE_FLOW, this.update); - }, - getAll: function () { - return this.flows; - }, - add: function (flow) { - return this.update(flow); - }, - add_bulk: function (flows) { - //Treat all previously received updates as newer than the bulk update. - //If they weren't newer, we're about to receive an update for them very soon. - var updates = this.flows; - this.flows = flows; - updates.forEach(function(flow){ - this._update(flow); - }.bind(this)); - this.emit("change"); - }, - _update: function(flow){ - var idx = _.findIndex(this.flows, function(f){ - return flow.id === f.id; - }); - - if(idx < 0){ - this.flows.push(flow); - //if(this.flows.length > 100){ - // this.flows.shift(); - //} - } else { - this.flows[idx] = flow; - } - }, - update: function(flow){ - this._update(flow); - this.emit("change"); - }, -}); - - -function _FlowStore() { - EventEmitter.call(this); -} -_.extend(_FlowStore.prototype, EventEmitter.prototype, { - getView: function (since) { - var view = new FlowView(this, !since); - - $.getJSON("/static/flows.json", function(flows){ - flows = flows.concat(_.cloneDeep(flows)).concat(_.cloneDeep(flows)); - var id = 1; - flows.forEach(function(flow){ - flow.id = "uuid-" + id++; - }); - view.add_bulk(flows); - - }); - - return view; - }, - handle: function (action) { - switch (action.type) { - case ActionTypes.ADD_FLOW: - case ActionTypes.UPDATE_FLOW: - this.emit(action.type, action.data); - break; - default: - return; - } - } -}); - - -var FlowStore = new _FlowStore(); -AppDispatcher.register(FlowStore.handle.bind(FlowStore)); diff --git a/web/src/js/stores/settingstore.js b/web/src/js/stores/settingstore.js deleted file mode 100644 index 7eef9b8f..00000000 --- a/web/src/js/stores/settingstore.js +++ /dev/null @@ -1,28 +0,0 @@ -function _SettingsStore() { - EventEmitter.call(this); - - //FIXME: What do we do if we haven't requested anything from the server yet? - this.settings = { - version: "0.12", - showEventLog: true, - mode: "transparent", - }; -} -_.extend(_SettingsStore.prototype, EventEmitter.prototype, { - getAll: function () { - return this.settings; - }, - handle: function (action) { - switch (action.type) { - case ActionTypes.UPDATE_SETTINGS: - this.settings = action.settings; - this.emit("change"); - break; - default: - return; - } - } -}); - -var SettingsStore = new _SettingsStore(); -AppDispatcher.register(SettingsStore.handle.bind(SettingsStore)); diff --git a/web/src/js/utils.js b/web/src/js/utils.js index fa15db8c..8ae7aa54 100644 --- a/web/src/js/utils.js +++ b/web/src/js/utils.js @@ -12,6 +12,7 @@ var AutoScrollMixin = { }, }; + var StickyHeadMixin = { adjustHead: function () { // Abusing CSS transforms to set the element @@ -21,6 +22,7 @@ var StickyHeadMixin = { } }; + var Key = { UP: 38, DOWN: 40, @@ -38,17 +40,19 @@ var Key = { L: 76 }; + var formatSize = function (bytes) { var size = bytes; var prefix = ["B", "KB", "MB", "GB", "TB"]; - var i=0; - while (Math.abs(size) >= 1024 && i < prefix.length-1) { + var i = 0; + while (Math.abs(size) >= 1024 && i < prefix.length - 1) { i++; size = size / 1024; } return (Math.floor(size * 100) / 100.0).toFixed(2) + prefix[i]; }; + var formatTimeDelta = function (milliseconds) { var time = milliseconds; var prefix = ["ms", "s", "min", "h"]; @@ -59,4 +63,41 @@ var formatTimeDelta = function (milliseconds) { i++; } return Math.round(time) + prefix[i]; +}; + + +var formatTimeStamp = function (seconds) { + var ts = (new Date(seconds * 1000)).toISOString(); + return ts.replace("T", " ").replace("Z", ""); +}; + + +function EventEmitter() { + this.listeners = {}; +} +EventEmitter.prototype.emit = function (event) { + if (!(event in this.listeners)) { + return; + } + var args = Array.prototype.slice.call(arguments, 1); + this.listeners[event].forEach(function (listener) { + listener.apply(this, args); + }.bind(this)); +}; +EventEmitter.prototype.addListener = function (events, f) { + events.split(" ").forEach(function (event) { + this.listeners[event] = this.listeners[event] || []; + this.listeners[event].push(f); + }.bind(this)); +}; +EventEmitter.prototype.removeListener = function (events, f) { + if (!(events in this.listeners)) { + return false; + } + events.split(" ").forEach(function (event) { + var index = this.listeners[event].indexOf(f); + if (index >= 0) { + this.listeners[event].splice(index, 1); + } + }.bind(this)); };
\ No newline at end of file diff --git a/web/src/vendor/bootstrap/bootstrap.css b/web/src/vendor/bootstrap/bootstrap.css index 037dd056..c6f3d210 100644 --- a/web/src/vendor/bootstrap/bootstrap.css +++ b/web/src/vendor/bootstrap/bootstrap.css @@ -1,10 +1,10 @@ /*! - * Bootstrap v3.2.0 (http://getbootstrap.com) + * Bootstrap v3.3.1 (http://getbootstrap.com) * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ -/*! normalize.css v3.0.1 | MIT License | git.io/normalize */ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ html { font-family: sans-serif; -webkit-text-size-adjust: 100%; @@ -22,6 +22,7 @@ footer, header, hgroup, main, +menu, nav, section, summary { @@ -43,7 +44,7 @@ template { display: none; } a { - background: transparent; + background-color: transparent; } a:active, a:hover { @@ -187,8 +188,11 @@ td, th { padding: 0; } +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ @media print { - * { + *, + *:before, + *:after { color: #000 !important; text-shadow: none !important; background: transparent !important; @@ -205,8 +209,8 @@ th { abbr[title]:after { content: " (" attr(title) ")"; } - a[href^="javascript:"]:after, - a[href^="#"]:after { + a[href^="#"]:after, + a[href^="javascript:"]:after { content: ""; } pre, @@ -241,10 +245,6 @@ th { .navbar { display: none; } - .table td, - .table th { - background-color: #fff !important; - } .btn > .caret, .dropup > .btn > .caret { border-top-color: #000 !important; @@ -255,6 +255,10 @@ th { .table { border-collapse: collapse !important; } + .table td, + .table th { + background-color: #fff !important; + } .table-bordered th, .table-bordered td { border: 1px solid #ddd !important; @@ -284,7 +288,8 @@ th { .glyphicon-plus:before { content: "\2b"; } -.glyphicon-euro:before { +.glyphicon-euro:before, +.glyphicon-eur:before { content: "\20ac"; } .glyphicon-minus:before { @@ -910,12 +915,12 @@ textarea { line-height: inherit; } a { - color: #428bca; + color: #337ab7; text-decoration: none; } a:hover, a:focus { - color: #2a6496; + color: #23527c; text-decoration: underline; } a:focus { @@ -935,7 +940,6 @@ img { .carousel-inner > .item > img, .carousel-inner > .item > a > img { display: block; - width: 100% \9; max-width: 100%; height: auto; } @@ -944,7 +948,6 @@ img { } .img-thumbnail { display: inline-block; - width: 100% \9; max-width: 100%; height: auto; padding: 4px; @@ -1117,9 +1120,6 @@ small, .small { font-size: 85%; } -cite { - font-style: normal; -} mark, .mark { padding: .2em; @@ -1153,10 +1153,10 @@ mark, color: #777; } .text-primary { - color: #428bca; + color: #337ab7; } a.text-primary:hover { - color: #3071a9; + color: #286090; } .text-success { color: #3c763d; @@ -1184,10 +1184,10 @@ a.text-danger:hover { } .bg-primary { color: #fff; - background-color: #428bca; + background-color: #337ab7; } a.bg-primary:hover { - background-color: #3071a9; + background-color: #286090; } .bg-success { background-color: #dff0d8; @@ -1328,10 +1328,6 @@ blockquote.pull-right small:after, blockquote.pull-right .small:after { content: '\00A0 \2014'; } -blockquote:before, -blockquote:after { - content: ""; -} address { margin-bottom: 20px; font-style: normal; @@ -1362,6 +1358,7 @@ kbd { kbd kbd { padding: 0; font-size: 100%; + font-weight: bold; -webkit-box-shadow: none; box-shadow: none; } @@ -2060,6 +2057,12 @@ pre code { table { background-color: transparent; } +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777; + text-align: left; +} th { text-align: left; } @@ -2120,12 +2123,10 @@ th { .table-bordered > thead > tr > td { border-bottom-width: 2px; } -.table-striped > tbody > tr:nth-child(odd) > td, -.table-striped > tbody > tr:nth-child(odd) > th { +.table-striped > tbody > tr:nth-child(odd) { background-color: #f9f9f9; } -.table-hover > tbody > tr:hover > td, -.table-hover > tbody > tr:hover > th { +.table-hover > tbody > tr:hover { background-color: #f5f5f5; } table col[class*="col-"] { @@ -2244,13 +2245,15 @@ table th[class*="col-"] { .table-hover > tbody > tr.danger:hover > th { background-color: #ebcccc; } +.table-responsive { + min-height: .01%; + overflow-x: auto; +} @media screen and (max-width: 767px) { .table-responsive { width: 100%; margin-bottom: 15px; - overflow-x: auto; overflow-y: hidden; - -webkit-overflow-scrolling: touch; -ms-overflow-style: -ms-autohiding-scrollbar; border: 1px solid #ddd; } @@ -2375,14 +2378,14 @@ output { box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); } .form-control::-moz-placeholder { - color: #777; + color: #999; opacity: 1; } .form-control:-ms-input-placeholder { - color: #777; + color: #999; } .form-control::-webkit-input-placeholder { - color: #777; + color: #999; } .form-control[disabled], .form-control[readonly], @@ -2397,24 +2400,25 @@ textarea.form-control { input[type="search"] { -webkit-appearance: none; } -input[type="date"], -input[type="time"], -input[type="datetime-local"], -input[type="month"] { - line-height: 34px; - line-height: 1.42857143 \0; -} -input[type="date"].input-sm, -input[type="time"].input-sm, -input[type="datetime-local"].input-sm, -input[type="month"].input-sm { - line-height: 30px; -} -input[type="date"].input-lg, -input[type="time"].input-lg, -input[type="datetime-local"].input-lg, -input[type="month"].input-lg { - line-height: 46px; +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"], + input[type="time"], + input[type="datetime-local"], + input[type="month"] { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg { + line-height: 46px; + } } .form-group { margin-bottom: 15px; @@ -2423,12 +2427,12 @@ input[type="month"].input-lg { .checkbox { position: relative; display: block; - min-height: 20px; margin-top: 10px; margin-bottom: 10px; } .radio label, .checkbox label { + min-height: 20px; padding-left: 20px; margin-bottom: 0; font-weight: normal; @@ -2491,35 +2495,41 @@ fieldset[disabled] .checkbox label { padding-left: 0; } .input-sm, -.form-horizontal .form-group-sm .form-control { +.form-group-sm .form-control { height: 30px; padding: 5px 10px; font-size: 12px; line-height: 1.5; border-radius: 3px; } -select.input-sm { +select.input-sm, +select.form-group-sm .form-control { height: 30px; line-height: 30px; } textarea.input-sm, -select[multiple].input-sm { +textarea.form-group-sm .form-control, +select[multiple].input-sm, +select[multiple].form-group-sm .form-control { height: auto; } .input-lg, -.form-horizontal .form-group-lg .form-control { +.form-group-lg .form-control { height: 46px; padding: 10px 16px; font-size: 18px; line-height: 1.33; border-radius: 6px; } -select.input-lg { +select.input-lg, +select.form-group-lg .form-control { height: 46px; line-height: 46px; } textarea.input-lg, -select[multiple].input-lg { +textarea.form-group-lg .form-control, +select[multiple].input-lg, +select[multiple].form-group-lg .form-control { height: auto; } .has-feedback { @@ -2530,7 +2540,7 @@ select[multiple].input-lg { } .form-control-feedback { position: absolute; - top: 25px; + top: 0; right: 0; z-index: 2; display: block; @@ -2538,6 +2548,7 @@ select[multiple].input-lg { height: 34px; line-height: 34px; text-align: center; + pointer-events: none; } .input-lg + .form-control-feedback { width: 46px; @@ -2554,7 +2565,11 @@ select[multiple].input-lg { .has-success .radio, .has-success .checkbox, .has-success .radio-inline, -.has-success .checkbox-inline { +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { color: #3c763d; } .has-success .form-control { @@ -2580,7 +2595,11 @@ select[multiple].input-lg { .has-warning .radio, .has-warning .checkbox, .has-warning .radio-inline, -.has-warning .checkbox-inline { +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { color: #8a6d3b; } .has-warning .form-control { @@ -2606,7 +2625,11 @@ select[multiple].input-lg { .has-error .radio, .has-error .checkbox, .has-error .radio-inline, -.has-error .checkbox-inline { +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { color: #a94442; } .has-error .form-control { @@ -2627,6 +2650,9 @@ select[multiple].input-lg { .has-error .form-control-feedback { color: #a94442; } +.has-feedback label ~ .form-control-feedback { + top: 25px; +} .has-feedback label.sr-only ~ .form-control-feedback { top: 0; } @@ -2647,6 +2673,9 @@ select[multiple].input-lg { width: auto; vertical-align: middle; } + .form-inline .form-control-static { + display: inline-block; + } .form-inline .input-group { display: inline-table; vertical-align: middle; @@ -2707,7 +2736,6 @@ select[multiple].input-lg { } } .form-horizontal .has-feedback .form-control-feedback { - top: 0; right: 15px; } @media (min-width: 768px) { @@ -2730,6 +2758,8 @@ select[multiple].input-lg { text-align: center; white-space: nowrap; vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; @@ -2741,13 +2771,17 @@ select[multiple].input-lg { } .btn:focus, .btn:active:focus, -.btn.active:focus { +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { outline: thin dotted; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } .btn:hover, -.btn:focus { +.btn:focus, +.btn.focus { color: #333; text-decoration: none; } @@ -2775,6 +2809,7 @@ fieldset[disabled] .btn { } .btn-default:hover, .btn-default:focus, +.btn-default.focus, .btn-default:active, .btn-default.active, .open > .dropdown-toggle.btn-default { @@ -2796,6 +2831,9 @@ fieldset[disabled] .btn-default:hover, .btn-default.disabled:focus, .btn-default[disabled]:focus, fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus, .btn-default.disabled:active, .btn-default[disabled]:active, fieldset[disabled] .btn-default:active, @@ -2811,17 +2849,18 @@ fieldset[disabled] .btn-default.active { } .btn-primary { color: #fff; - background-color: #428bca; - border-color: #357ebd; + background-color: #337ab7; + border-color: #2e6da4; } .btn-primary:hover, .btn-primary:focus, +.btn-primary.focus, .btn-primary:active, .btn-primary.active, .open > .dropdown-toggle.btn-primary { color: #fff; - background-color: #3071a9; - border-color: #285e8e; + background-color: #286090; + border-color: #204d74; } .btn-primary:active, .btn-primary.active, @@ -2837,17 +2876,20 @@ fieldset[disabled] .btn-primary:hover, .btn-primary.disabled:focus, .btn-primary[disabled]:focus, fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus, .btn-primary.disabled:active, .btn-primary[disabled]:active, fieldset[disabled] .btn-primary:active, .btn-primary.disabled.active, .btn-primary[disabled].active, fieldset[disabled] .btn-primary.active { - background-color: #428bca; - border-color: #357ebd; + background-color: #337ab7; + border-color: #2e6da4; } .btn-primary .badge { - color: #428bca; + color: #337ab7; background-color: #fff; } .btn-success { @@ -2857,6 +2899,7 @@ fieldset[disabled] .btn-primary.active { } .btn-success:hover, .btn-success:focus, +.btn-success.focus, .btn-success:active, .btn-success.active, .open > .dropdown-toggle.btn-success { @@ -2878,6 +2921,9 @@ fieldset[disabled] .btn-success:hover, .btn-success.disabled:focus, .btn-success[disabled]:focus, fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus, .btn-success.disabled:active, .btn-success[disabled]:active, fieldset[disabled] .btn-success:active, @@ -2898,6 +2944,7 @@ fieldset[disabled] .btn-success.active { } .btn-info:hover, .btn-info:focus, +.btn-info.focus, .btn-info:active, .btn-info.active, .open > .dropdown-toggle.btn-info { @@ -2919,6 +2966,9 @@ fieldset[disabled] .btn-info:hover, .btn-info.disabled:focus, .btn-info[disabled]:focus, fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus, .btn-info.disabled:active, .btn-info[disabled]:active, fieldset[disabled] .btn-info:active, @@ -2939,6 +2989,7 @@ fieldset[disabled] .btn-info.active { } .btn-warning:hover, .btn-warning:focus, +.btn-warning.focus, .btn-warning:active, .btn-warning.active, .open > .dropdown-toggle.btn-warning { @@ -2960,6 +3011,9 @@ fieldset[disabled] .btn-warning:hover, .btn-warning.disabled:focus, .btn-warning[disabled]:focus, fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus, .btn-warning.disabled:active, .btn-warning[disabled]:active, fieldset[disabled] .btn-warning:active, @@ -2980,6 +3034,7 @@ fieldset[disabled] .btn-warning.active { } .btn-danger:hover, .btn-danger:focus, +.btn-danger.focus, .btn-danger:active, .btn-danger.active, .open > .dropdown-toggle.btn-danger { @@ -3001,6 +3056,9 @@ fieldset[disabled] .btn-danger:hover, .btn-danger.disabled:focus, .btn-danger[disabled]:focus, fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus, .btn-danger.disabled:active, .btn-danger[disabled]:active, fieldset[disabled] .btn-danger:active, @@ -3016,12 +3074,12 @@ fieldset[disabled] .btn-danger.active { } .btn-link { font-weight: normal; - color: #428bca; - cursor: pointer; + color: #337ab7; border-radius: 0; } .btn-link, .btn-link:active, +.btn-link.active, .btn-link[disabled], fieldset[disabled] .btn-link { background-color: transparent; @@ -3036,7 +3094,7 @@ fieldset[disabled] .btn-link { } .btn-link:hover, .btn-link:focus { - color: #2a6496; + color: #23527c; text-decoration: underline; background-color: transparent; } @@ -3091,9 +3149,11 @@ input[type="button"].btn-block { } .collapse { display: none; + visibility: hidden; } .collapse.in { display: block; + visibility: visible; } tr.collapse.in { display: table-row; @@ -3105,9 +3165,15 @@ tbody.collapse.in { position: relative; height: 0; overflow: hidden; - -webkit-transition: height .35s ease; - -o-transition: height .35s ease; - transition: height .35s ease; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; + -webkit-transition-duration: .35s; + -o-transition-duration: .35s; + transition-duration: .35s; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; } .caret { display: inline-block; @@ -3177,7 +3243,7 @@ tbody.collapse.in { .dropdown-menu > .active > a:focus { color: #fff; text-decoration: none; - background-color: #428bca; + background-color: #337ab7; outline: 0; } .dropdown-menu > .disabled > a, @@ -3270,10 +3336,6 @@ tbody.collapse.in { .btn-group-vertical > .btn.active { z-index: 2; } -.btn-group > .btn:focus, -.btn-group-vertical > .btn:focus { - outline: 0; -} .btn-group .btn + .btn, .btn-group .btn + .btn-group, .btn-group .btn-group + .btn, @@ -3413,12 +3475,13 @@ tbody.collapse.in { .btn-group-justified > .btn-group .dropdown-menu { left: auto; } -[data-toggle="buttons"] > .btn > input[type="radio"], -[data-toggle="buttons"] > .btn > input[type="checkbox"] { +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { position: absolute; - z-index: -1; - filter: alpha(opacity=0); - opacity: 0; + clip: rect(0, 0, 0, 0); + pointer-events: none; } .input-group { position: relative; @@ -3607,7 +3670,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .nav .open > a:hover, .nav .open > a:focus { background-color: #eee; - border-color: #428bca; + border-color: #337ab7; } .nav .nav-divider { height: 1px; @@ -3700,7 +3763,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus { color: #fff; - background-color: #428bca; + background-color: #337ab7; } .nav-stacked > li { float: none; @@ -3757,9 +3820,11 @@ select[multiple].input-group-sm > .input-group-btn > .btn { } .tab-content > .tab-pane { display: none; + visibility: hidden; } .tab-content > .active { display: block; + visibility: visible; } .nav-tabs .dropdown-menu { margin-top: -1px; @@ -3806,6 +3871,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { height: auto !important; padding-bottom: 0; overflow: visible !important; + visibility: visible !important; } .navbar-collapse.in { overflow-y: visible; @@ -3821,7 +3887,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .navbar-fixed-bottom .navbar-collapse { max-height: 340px; } -@media (max-width: 480px) and (orientation: landscape) { +@media (max-device-width: 480px) and (orientation: landscape) { .navbar-fixed-top .navbar-collapse, .navbar-fixed-bottom .navbar-collapse { max-height: 200px; @@ -3858,9 +3924,6 @@ select[multiple].input-group-sm > .input-group-btn > .btn { right: 0; left: 0; z-index: 1030; - -webkit-transform: translate3d(0, 0, 0); - -o-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); } @media (min-width: 768px) { .navbar-fixed-top, @@ -3888,6 +3951,9 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .navbar-brand:focus { text-decoration: none; } +.navbar-brand > img { + display: block; +} @media (min-width: 768px) { .navbar > .container .navbar-brand, .navbar > .container-fluid .navbar-brand { @@ -3966,17 +4032,6 @@ select[multiple].input-group-sm > .input-group-btn > .btn { padding-top: 15px; padding-bottom: 15px; } - .navbar-nav.navbar-right:last-child { - margin-right: -15px; - } -} -@media (min-width: 768px) { - .navbar-left { - float: left !important; - } - .navbar-right { - float: right !important; - } } .navbar-form { padding: 10px 15px; @@ -4000,6 +4055,9 @@ select[multiple].input-group-sm > .input-group-btn > .btn { width: auto; vertical-align: middle; } + .navbar-form .form-control-static { + display: inline-block; + } .navbar-form .input-group { display: inline-table; vertical-align: middle; @@ -4040,6 +4098,9 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .navbar-form .form-group { margin-bottom: 5px; } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } } @media (min-width: 768px) { .navbar-form { @@ -4052,9 +4113,6 @@ select[multiple].input-group-sm > .input-group-btn > .btn { -webkit-box-shadow: none; box-shadow: none; } - .navbar-form.navbar-right:last-child { - margin-right: -15px; - } } .navbar-nav > li > .dropdown-menu { margin-top: 0; @@ -4062,6 +4120,8 @@ select[multiple].input-group-sm > .input-group-btn > .btn { border-top-right-radius: 0; } .navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + border-top-left-radius: 4px; + border-top-right-radius: 4px; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } @@ -4087,7 +4147,16 @@ select[multiple].input-group-sm > .input-group-btn > .btn { margin-right: 15px; margin-left: 15px; } - .navbar-text.navbar-right:last-child { +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { margin-right: 0; } } @@ -4192,7 +4261,7 @@ fieldset[disabled] .navbar-default .btn-link:focus { border-color: #080808; } .navbar-inverse .navbar-brand { - color: #777; + color: #9d9d9d; } .navbar-inverse .navbar-brand:hover, .navbar-inverse .navbar-brand:focus { @@ -4200,10 +4269,10 @@ fieldset[disabled] .navbar-default .btn-link:focus { background-color: transparent; } .navbar-inverse .navbar-text { - color: #777; + color: #9d9d9d; } .navbar-inverse .navbar-nav > li > a { - color: #777; + color: #9d9d9d; } .navbar-inverse .navbar-nav > li > a:hover, .navbar-inverse .navbar-nav > li > a:focus { @@ -4250,7 +4319,7 @@ fieldset[disabled] .navbar-default .btn-link:focus { background-color: #080808; } .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { - color: #777; + color: #9d9d9d; } .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { @@ -4271,13 +4340,13 @@ fieldset[disabled] .navbar-default .btn-link:focus { } } .navbar-inverse .navbar-link { - color: #777; + color: #9d9d9d; } .navbar-inverse .navbar-link:hover { color: #fff; } .navbar-inverse .btn-link { - color: #777; + color: #9d9d9d; } .navbar-inverse .btn-link:hover, .navbar-inverse .btn-link:focus { @@ -4323,7 +4392,7 @@ fieldset[disabled] .navbar-inverse .btn-link:focus { padding: 6px 12px; margin-left: -1px; line-height: 1.42857143; - color: #428bca; + color: #337ab7; text-decoration: none; background-color: #fff; border: 1px solid #ddd; @@ -4343,7 +4412,7 @@ fieldset[disabled] .navbar-inverse .btn-link:focus { .pagination > li > span:hover, .pagination > li > a:focus, .pagination > li > span:focus { - color: #2a6496; + color: #23527c; background-color: #eee; border-color: #ddd; } @@ -4356,8 +4425,8 @@ fieldset[disabled] .navbar-inverse .btn-link:focus { z-index: 2; color: #fff; cursor: default; - background-color: #428bca; - border-color: #428bca; + background-color: #337ab7; + border-color: #337ab7; } .pagination > .disabled > span, .pagination > .disabled > span:hover, @@ -4471,11 +4540,11 @@ a.label:focus { background-color: #5e5e5e; } .label-primary { - background-color: #428bca; + background-color: #337ab7; } .label-primary[href]:hover, .label-primary[href]:focus { - background-color: #3071a9; + background-color: #286090; } .label-success { background-color: #5cb85c; @@ -4536,16 +4605,22 @@ a.badge:focus { text-decoration: none; cursor: pointer; } -a.list-group-item.active > .badge, +.list-group-item.active > .badge, .nav-pills > .active > a > .badge { - color: #428bca; + color: #337ab7; background-color: #fff; } +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} .nav-pills > li > a > .badge { margin-left: 3px; } .jumbotron { - padding: 30px; + padding: 30px 15px; margin-bottom: 30px; color: inherit; background-color: #eee; @@ -4562,7 +4637,8 @@ a.list-group-item.active > .badge, .jumbotron > hr { border-top-color: #d5d5d5; } -.container .jumbotron { +.container .jumbotron, +.container-fluid .jumbotron { border-radius: 6px; } .jumbotron .container { @@ -4570,10 +4646,10 @@ a.list-group-item.active > .badge, } @media screen and (min-width: 768px) { .jumbotron { - padding-top: 48px; - padding-bottom: 48px; + padding: 48px 0; } - .container .jumbotron { + .container .jumbotron, + .container-fluid .jumbotron { padding-right: 60px; padding-left: 60px; } @@ -4590,9 +4666,9 @@ a.list-group-item.active > .badge, background-color: #fff; border: 1px solid #ddd; border-radius: 4px; - -webkit-transition: all .2s ease-in-out; - -o-transition: all .2s ease-in-out; - transition: all .2s ease-in-out; + -webkit-transition: border .2s ease-in-out; + -o-transition: border .2s ease-in-out; + transition: border .2s ease-in-out; } .thumbnail > img, .thumbnail a > img { @@ -4602,7 +4678,7 @@ a.list-group-item.active > .badge, a.thumbnail:hover, a.thumbnail:focus, a.thumbnail.active { - border-color: #428bca; + border-color: #337ab7; } .thumbnail .caption { padding: 9px; @@ -4724,7 +4800,7 @@ a.thumbnail.active { line-height: 20px; color: #fff; text-align: center; - background-color: #428bca; + background-color: #337ab7; -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); -webkit-transition: width .6s ease; @@ -4745,18 +4821,6 @@ a.thumbnail.active { -o-animation: progress-bar-stripes 2s linear infinite; animation: progress-bar-stripes 2s linear infinite; } -.progress-bar[aria-valuenow="1"], -.progress-bar[aria-valuenow="2"] { - min-width: 30px; -} -.progress-bar[aria-valuenow="0"] { - min-width: 30px; - color: #777; - background-color: transparent; - background-image: none; - -webkit-box-shadow: none; - box-shadow: none; -} .progress-bar-success { background-color: #5cb85c; } @@ -4789,29 +4853,35 @@ a.thumbnail.active { background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); } -.media, -.media-body { - overflow: hidden; - zoom: 1; -} -.media, -.media .media { +.media { margin-top: 15px; } .media:first-child { margin-top: 0; } -.media-object { - display: block; -} -.media-heading { - margin: 0 0 5px; +.media-right, +.media > .pull-right { + padding-left: 10px; } +.media-left, .media > .pull-left { - margin-right: 10px; + padding-right: 10px; } -.media > .pull-right { - margin-left: 10px; +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; } .media-list { padding-left: 0; @@ -4838,12 +4908,6 @@ a.thumbnail.active { border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; } -.list-group-item > .badge { - float: right; -} -.list-group-item > .badge + .badge { - margin-right: 5px; -} a.list-group-item { color: #555; } @@ -4860,6 +4924,7 @@ a.list-group-item:focus { .list-group-item.disabled:hover, .list-group-item.disabled:focus { color: #777; + cursor: not-allowed; background-color: #eee; } .list-group-item.disabled .list-group-item-heading, @@ -4877,8 +4942,8 @@ a.list-group-item:focus { .list-group-item.active:focus { z-index: 2; color: #fff; - background-color: #428bca; - border-color: #428bca; + background-color: #337ab7; + border-color: #337ab7; } .list-group-item.active .list-group-item-heading, .list-group-item.active:hover .list-group-item-heading, @@ -4894,7 +4959,7 @@ a.list-group-item:focus { .list-group-item.active .list-group-item-text, .list-group-item.active:hover .list-group-item-text, .list-group-item.active:focus .list-group-item-text { - color: #e1edf7; + color: #c7ddef; } .list-group-item-success { color: #3c763d; @@ -5028,19 +5093,23 @@ a.list-group-item-danger.active:focus { border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; } -.panel > .list-group { +.panel > .list-group, +.panel > .panel-collapse > .list-group { margin-bottom: 0; } -.panel > .list-group .list-group-item { +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { border-width: 1px 0; border-radius: 0; } -.panel > .list-group:first-child .list-group-item:first-child { +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { border-top: 0; border-top-left-radius: 3px; border-top-right-radius: 3px; } -.panel > .list-group:last-child .list-group-item:last-child { +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { border-bottom: 0; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; @@ -5056,11 +5125,24 @@ a.list-group-item-danger.active:focus { .panel > .panel-collapse > .table { margin-bottom: 0; } +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-right: 15px; + padding-left: 15px; +} .panel > .table:first-child, .panel > .table-responsive:first-child > .table:first-child { border-top-left-radius: 3px; border-top-right-radius: 3px; } +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} .panel > .table:first-child > thead:first-child > tr:first-child td:first-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, .panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, @@ -5086,6 +5168,13 @@ a.list-group-item-danger.active:focus { border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; } +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} .panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, .panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, @@ -5107,7 +5196,9 @@ a.list-group-item-danger.active:focus { border-bottom-right-radius: 3px; } .panel > .panel-body + .table, -.panel > .panel-body + .table-responsive { +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { border-top: 1px solid #ddd; } .panel > .table > tbody:first-child > tr:first-child th, @@ -5183,7 +5274,8 @@ a.list-group-item-danger.active:focus { .panel-group .panel-heading { border-bottom: 0; } -.panel-group .panel-heading + .panel-collapse > .panel-body { +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { border-top: 1px solid #ddd; } .panel-group .panel-footer { @@ -5211,22 +5303,22 @@ a.list-group-item-danger.active:focus { border-bottom-color: #ddd; } .panel-primary { - border-color: #428bca; + border-color: #337ab7; } .panel-primary > .panel-heading { color: #fff; - background-color: #428bca; - border-color: #428bca; + background-color: #337ab7; + border-color: #337ab7; } .panel-primary > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #428bca; + border-top-color: #337ab7; } .panel-primary > .panel-heading .badge { - color: #428bca; + color: #337ab7; background-color: #fff; } .panel-primary > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #428bca; + border-bottom-color: #337ab7; } .panel-success { border-color: #d6e9c6; @@ -5310,7 +5402,8 @@ a.list-group-item-danger.active:focus { .embed-responsive .embed-responsive-item, .embed-responsive iframe, .embed-responsive embed, -.embed-responsive object { +.embed-responsive object, +.embed-responsive video { position: absolute; top: 0; bottom: 0; @@ -5381,7 +5474,7 @@ button.close { right: 0; bottom: 0; left: 0; - z-index: 1050; + z-index: 1040; display: none; overflow: hidden; -webkit-overflow-scrolling: touch; @@ -5391,14 +5484,16 @@ button.close { -webkit-transition: -webkit-transform .3s ease-out; -o-transition: -o-transform .3s ease-out; transition: transform .3s ease-out; - -webkit-transform: translate3d(0, -25%, 0); - -o-transform: translate3d(0, -25%, 0); - transform: translate3d(0, -25%, 0); + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); } .modal.in .modal-dialog { - -webkit-transform: translate3d(0, 0, 0); - -o-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); } .modal-open .modal { overflow-x: hidden; @@ -5422,12 +5517,10 @@ button.close { box-shadow: 0 3px 9px rgba(0, 0, 0, .5); } .modal-backdrop { - position: fixed; + position: absolute; top: 0; right: 0; - bottom: 0; left: 0; - z-index: 1040; background-color: #000; } .modal-backdrop.fade { @@ -5498,7 +5591,9 @@ button.close { position: absolute; z-index: 1070; display: block; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 12px; + font-weight: normal; line-height: 1.4; visibility: visible; filter: alpha(opacity=0); @@ -5548,14 +5643,16 @@ button.close { border-top-color: #000; } .tooltip.top-left .tooltip-arrow { + right: 5px; bottom: 0; - left: 5px; + margin-bottom: -5px; border-width: 5px 5px 0; border-top-color: #000; } .tooltip.top-right .tooltip-arrow { - right: 5px; bottom: 0; + left: 5px; + margin-bottom: -5px; border-width: 5px 5px 0; border-top-color: #000; } @@ -5582,13 +5679,15 @@ button.close { } .tooltip.bottom-left .tooltip-arrow { top: 0; - left: 5px; + right: 5px; + margin-top: -5px; border-width: 0 5px 5px; border-bottom-color: #000; } .tooltip.bottom-right .tooltip-arrow { top: 0; - right: 5px; + left: 5px; + margin-top: -5px; border-width: 0 5px 5px; border-bottom-color: #000; } @@ -5600,6 +5699,10 @@ button.close { display: none; max-width: 276px; padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; text-align: left; white-space: normal; background-color: #fff; @@ -5627,8 +5730,6 @@ button.close { padding: 8px 14px; margin: 0; font-size: 14px; - font-weight: normal; - line-height: 18px; background-color: #f7f7f7; border-bottom: 1px solid #ebebeb; border-radius: 5px 5px 0 0; @@ -5731,6 +5832,37 @@ button.close { .carousel-inner > .item > a > img { line-height: 1; } +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform .6s ease-in-out; + -o-transition: -o-transform .6s ease-in-out; + transition: transform .6s ease-in-out; + + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000; + perspective: 1000; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + left: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + left: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + left: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} .carousel-inner > .active, .carousel-inner > .next, .carousel-inner > .prev { @@ -5986,9 +6118,6 @@ button.close { } .affix { position: fixed; - -webkit-transform: translate3d(0, 0, 0); - -o-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); } @-ms-viewport { width: device-width; diff --git a/web/src/vendor/bootstrap/bootstrap.js b/web/src/vendor/bootstrap/bootstrap.js index 53da1c77..b6ac8d99 100644 --- a/web/src/vendor/bootstrap/bootstrap.js +++ b/web/src/vendor/bootstrap/bootstrap.js @@ -1,13 +1,22 @@ /*! - * Bootstrap v3.2.0 (http://getbootstrap.com) + * Bootstrap v3.3.1 (http://getbootstrap.com) * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ -if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery') } +if (typeof jQuery === 'undefined') { + throw new Error('Bootstrap\'s JavaScript requires jQuery') +} + ++function ($) { + var version = $.fn.jquery.split(' ')[0].split('.') + if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) { + throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher') + } +}(jQuery); /* ======================================================================== - * Bootstrap: transition.js v3.2.0 + * Bootstrap: transition.js v3.3.1 * http://getbootstrap.com/javascript/#transitions * ======================================================================== * Copyright 2011-2014 Twitter, Inc. @@ -67,7 +76,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re }(jQuery); /* ======================================================================== - * Bootstrap: alert.js v3.2.0 + * Bootstrap: alert.js v3.3.1 * http://getbootstrap.com/javascript/#alerts * ======================================================================== * Copyright 2011-2014 Twitter, Inc. @@ -86,7 +95,9 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re $(el).on('click', dismiss, this.close) } - Alert.VERSION = '3.2.0' + Alert.VERSION = '3.3.1' + + Alert.TRANSITION_DURATION = 150 Alert.prototype.close = function (e) { var $this = $(this) @@ -102,7 +113,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re if (e) e.preventDefault() if (!$parent.length) { - $parent = $this.hasClass('alert') ? $this : $this.parent() + $parent = $this.closest('.alert') } $parent.trigger(e = $.Event('close.bs.alert')) @@ -119,7 +130,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re $.support.transition && $parent.hasClass('fade') ? $parent .one('bsTransitionEnd', removeElement) - .emulateTransitionEnd(150) : + .emulateTransitionEnd(Alert.TRANSITION_DURATION) : removeElement() } @@ -160,7 +171,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re }(jQuery); /* ======================================================================== - * Bootstrap: button.js v3.2.0 + * Bootstrap: button.js v3.3.1 * http://getbootstrap.com/javascript/#buttons * ======================================================================== * Copyright 2011-2014 Twitter, Inc. @@ -180,7 +191,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re this.isLoading = false } - Button.VERSION = '3.2.0' + Button.VERSION = '3.3.1' Button.DEFAULTS = { loadingText: 'loading...' @@ -196,10 +207,10 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re if (data.resetText == null) $el.data('resetText', $el[val]()) - $el[val](data[state] == null ? this.options[state] : data[state]) - // push to event loop to allow forms to submit setTimeout($.proxy(function () { + $el[val](data[state] == null ? this.options[state] : data[state]) + if (state == 'loadingText') { this.isLoading = true $el.addClass(d).attr(d, d) @@ -221,6 +232,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re else $parent.find('.active').removeClass('active') } if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') + } else { + this.$element.attr('aria-pressed', !this.$element.hasClass('active')) } if (changed) this.$element.toggleClass('active') @@ -261,17 +274,21 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re // BUTTON DATA-API // =============== - $(document).on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - Plugin.call($btn, 'toggle') - e.preventDefault() - }) + $(document) + .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + Plugin.call($btn, 'toggle') + e.preventDefault() + }) + .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { + $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) + }) }(jQuery); /* ======================================================================== - * Bootstrap: carousel.js v3.2.0 + * Bootstrap: carousel.js v3.3.1 * http://getbootstrap.com/javascript/#carousel * ======================================================================== * Copyright 2011-2014 Twitter, Inc. @@ -286,7 +303,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re // ========================= var Carousel = function (element, options) { - this.$element = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this)) + this.$element = $(element) this.$indicators = this.$element.find('.carousel-indicators') this.options = options this.paused = @@ -295,20 +312,26 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re this.$active = this.$items = null - this.options.pause == 'hover' && this.$element + this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) + + this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) } - Carousel.VERSION = '3.2.0' + Carousel.VERSION = '3.3.1' + + Carousel.TRANSITION_DURATION = 600 Carousel.DEFAULTS = { interval: 5000, pause: 'hover', - wrap: true + wrap: true, + keyboard: true } Carousel.prototype.keydown = function (e) { + if (/input|textarea/i.test(e.target.tagName)) return switch (e.which) { case 37: this.prev(); break case 39: this.next(); break @@ -335,6 +358,13 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re return this.$items.index(item || this.$active) } + Carousel.prototype.getItemForDirection = function (direction, active) { + var delta = direction == 'prev' ? -1 : 1 + var activeIndex = this.getItemIndex(active) + var itemIndex = (activeIndex + delta) % this.$items.length + return this.$items.eq(itemIndex) + } + Carousel.prototype.to = function (pos) { var that = this var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) @@ -344,7 +374,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" if (activeIndex == pos) return this.pause().cycle() - return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) + return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) } Carousel.prototype.pause = function (e) { @@ -372,7 +402,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re Carousel.prototype.slide = function (type, next) { var $active = this.$element.find('.item.active') - var $next = next || $active[type]() + var $next = next || this.getItemForDirection(type, $active) var isCycling = this.interval var direction = type == 'next' ? 'left' : 'right' var fallback = type == 'next' ? 'first' : 'last' @@ -418,7 +448,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re that.$element.trigger(slidEvent) }, 0) }) - .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000) + .emulateTransitionEnd(Carousel.TRANSITION_DURATION) } else { $active.removeClass('active') $next.addClass('active') @@ -467,7 +497,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re // CAROUSEL DATA-API // ================= - $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { + var clickHandler = function (e) { var href var $this = $(this) var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 @@ -483,7 +513,11 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re } e.preventDefault() - }) + } + + $(document) + .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) + .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) $(window).on('load', function () { $('[data-ride="carousel"]').each(function () { @@ -495,7 +529,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re }(jQuery); /* ======================================================================== - * Bootstrap: collapse.js v3.2.0 + * Bootstrap: collapse.js v3.3.1 * http://getbootstrap.com/javascript/#collapse * ======================================================================== * Copyright 2011-2014 Twitter, Inc. @@ -512,16 +546,25 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re var Collapse = function (element, options) { this.$element = $(element) this.options = $.extend({}, Collapse.DEFAULTS, options) + this.$trigger = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]') this.transitioning = null - if (this.options.parent) this.$parent = $(this.options.parent) + if (this.options.parent) { + this.$parent = this.getParent() + } else { + this.addAriaAndCollapsedClass(this.$element, this.$trigger) + } + if (this.options.toggle) this.toggle() } - Collapse.VERSION = '3.2.0' + Collapse.VERSION = '3.3.1' + + Collapse.TRANSITION_DURATION = 350 Collapse.DEFAULTS = { - toggle: true + toggle: true, + trigger: '[data-toggle="collapse"]' } Collapse.prototype.dimension = function () { @@ -532,17 +575,21 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re Collapse.prototype.show = function () { if (this.transitioning || this.$element.hasClass('in')) return + var activesData + var actives = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing') + + if (actives && actives.length) { + activesData = actives.data('bs.collapse') + if (activesData && activesData.transitioning) return + } + var startEvent = $.Event('show.bs.collapse') this.$element.trigger(startEvent) if (startEvent.isDefaultPrevented()) return - var actives = this.$parent && this.$parent.find('> .panel > .in') - if (actives && actives.length) { - var hasData = actives.data('bs.collapse') - if (hasData && hasData.transitioning) return Plugin.call(actives, 'hide') - hasData || actives.data('bs.collapse', null) + activesData || actives.data('bs.collapse', null) } var dimension = this.dimension() @@ -550,6 +597,11 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re this.$element .removeClass('collapse') .addClass('collapsing')[dimension](0) + .attr('aria-expanded', true) + + this.$trigger + .removeClass('collapsed') + .attr('aria-expanded', true) this.transitioning = 1 @@ -568,7 +620,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re this.$element .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) + .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) } Collapse.prototype.hide = function () { @@ -584,17 +636,21 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re this.$element .addClass('collapsing') - .removeClass('collapse') - .removeClass('in') + .removeClass('collapse in') + .attr('aria-expanded', false) + + this.$trigger + .addClass('collapsed') + .attr('aria-expanded', false) this.transitioning = 1 var complete = function () { this.transitioning = 0 this.$element - .trigger('hidden.bs.collapse') .removeClass('collapsing') .addClass('collapse') + .trigger('hidden.bs.collapse') } if (!$.support.transition) return complete.call(this) @@ -602,13 +658,40 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re this.$element [dimension](0) .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(350) + .emulateTransitionEnd(Collapse.TRANSITION_DURATION) } Collapse.prototype.toggle = function () { this[this.$element.hasClass('in') ? 'hide' : 'show']() } + Collapse.prototype.getParent = function () { + return $(this.options.parent) + .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') + .each($.proxy(function (i, element) { + var $element = $(element) + this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) + }, this)) + .end() + } + + Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { + var isOpen = $element.hasClass('in') + + $element.attr('aria-expanded', isOpen) + $trigger + .toggleClass('collapsed', !isOpen) + .attr('aria-expanded', isOpen) + } + + function getTargetFromTrigger($trigger) { + var href + var target = $trigger.attr('data-target') + || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 + + return $(target) + } + // COLLAPSE PLUGIN DEFINITION // ========================== @@ -619,7 +702,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re var data = $this.data('bs.collapse') var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) - if (!data && options.toggle && option == 'show') option = !option + if (!data && options.toggle && option == 'show') options.toggle = false if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) if (typeof option == 'string') data[option]() }) @@ -644,21 +727,13 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re // ================= $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { - var href var $this = $(this) - var target = $this.attr('data-target') - || e.preventDefault() - || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 - var $target = $(target) - var data = $target.data('bs.collapse') - var option = data ? 'toggle' : $this.data() - var parent = $this.attr('data-parent') - var $parent = parent && $(parent) - if (!data || !data.transitioning) { - if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') - $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') - } + if (!$this.attr('data-target')) e.preventDefault() + + var $target = getTargetFromTrigger($this) + var data = $target.data('bs.collapse') + var option = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this }) Plugin.call($target, option) }) @@ -666,7 +741,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re }(jQuery); /* ======================================================================== - * Bootstrap: dropdown.js v3.2.0 + * Bootstrap: dropdown.js v3.3.1 * http://getbootstrap.com/javascript/#dropdowns * ======================================================================== * Copyright 2011-2014 Twitter, Inc. @@ -686,7 +761,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re $(element).on('click.bs.dropdown', this.toggle) } - Dropdown.VERSION = '3.2.0' + Dropdown.VERSION = '3.3.1' Dropdown.prototype.toggle = function (e) { var $this = $(this) @@ -709,7 +784,9 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re if (e.isDefaultPrevented()) return - $this.trigger('focus') + $this + .trigger('focus') + .attr('aria-expanded', 'true') $parent .toggleClass('open') @@ -720,7 +797,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re } Dropdown.prototype.keydown = function (e) { - if (!/(38|40|27)/.test(e.keyCode)) return + if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return var $this = $(this) @@ -732,7 +809,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re var $parent = getParent($this) var isActive = $parent.hasClass('open') - if (!isActive || (isActive && e.keyCode == 27)) { + if ((!isActive && e.which != 27) || (isActive && e.which == 27)) { if (e.which == 27) $parent.find(toggle).trigger('focus') return $this.trigger('click') } @@ -742,10 +819,10 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re if (!$items.length) return - var index = $items.index($items.filter(':focus')) + var index = $items.index(e.target) - if (e.keyCode == 38 && index > 0) index-- // up - if (e.keyCode == 40 && index < $items.length - 1) index++ // down + if (e.which == 38 && index > 0) index-- // up + if (e.which == 40 && index < $items.length - 1) index++ // down if (!~index) index = 0 $items.eq(index).trigger('focus') @@ -755,11 +832,17 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re if (e && e.which === 3) return $(backdrop).remove() $(toggle).each(function () { - var $parent = getParent($(this)) + var $this = $(this) + var $parent = getParent($this) var relatedTarget = { relatedTarget: this } + if (!$parent.hasClass('open')) return + $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) + if (e.isDefaultPrevented()) return + + $this.attr('aria-expanded', 'false') $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget) }) } @@ -813,12 +896,14 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re .on('click.bs.dropdown.data-api', clearMenus) .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) - .on('keydown.bs.dropdown.data-api', toggle + ', [role="menu"], [role="listbox"]', Dropdown.prototype.keydown) + .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) + .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown) + .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown) }(jQuery); /* ======================================================================== - * Bootstrap: modal.js v3.2.0 + * Bootstrap: modal.js v3.3.1 * http://getbootstrap.com/javascript/#modals * ======================================================================== * Copyright 2011-2014 Twitter, Inc. @@ -849,7 +934,10 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re } } - Modal.VERSION = '3.2.0' + Modal.VERSION = '3.3.1' + + Modal.TRANSITION_DURATION = 300 + Modal.BACKDROP_TRANSITION_DURATION = 150 Modal.DEFAULTS = { backdrop: true, @@ -872,10 +960,11 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re this.isShown = true this.checkScrollbar() + this.setScrollbar() this.$body.addClass('modal-open') - this.setScrollbar() this.escape() + this.resize() this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) @@ -890,6 +979,9 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re .show() .scrollTop(0) + if (that.options.backdrop) that.adjustBackdrop() + that.adjustDialog() + if (transition) { that.$element[0].offsetWidth // force reflow } @@ -907,7 +999,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re .one('bsTransitionEnd', function () { that.$element.trigger('focus').trigger(e) }) - .emulateTransitionEnd(300) : + .emulateTransitionEnd(Modal.TRANSITION_DURATION) : that.$element.trigger('focus').trigger(e) }) } @@ -923,10 +1015,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re this.isShown = false - this.$body.removeClass('modal-open') - - this.resetScrollbar() this.escape() + this.resize() $(document).off('focusin.bs.modal') @@ -938,7 +1028,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re $.support.transition && this.$element.hasClass('fade') ? this.$element .one('bsTransitionEnd', $.proxy(this.hideModal, this)) - .emulateTransitionEnd(300) : + .emulateTransitionEnd(Modal.TRANSITION_DURATION) : this.hideModal() } @@ -954,11 +1044,19 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re Modal.prototype.escape = function () { if (this.isShown && this.options.keyboard) { - this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) { + this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { e.which == 27 && this.hide() }, this)) } else if (!this.isShown) { - this.$element.off('keyup.dismiss.bs.modal') + this.$element.off('keydown.dismiss.bs.modal') + } + } + + Modal.prototype.resize = function () { + if (this.isShown) { + $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) + } else { + $(window).off('resize.bs.modal') } } @@ -966,6 +1064,9 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re var that = this this.$element.hide() this.backdrop(function () { + that.$body.removeClass('modal-open') + that.resetAdjustments() + that.resetScrollbar() that.$element.trigger('hidden.bs.modal') }) } @@ -983,14 +1084,13 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re var doAnimate = $.support.transition && animate this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />') - .appendTo(this.$body) - - this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { - if (e.target !== e.currentTarget) return - this.options.backdrop == 'static' - ? this.$element[0].focus.call(this.$element[0]) - : this.hide.call(this) - }, this)) + .prependTo(this.$element) + .on('click.dismiss.bs.modal', $.proxy(function (e) { + if (e.target !== e.currentTarget) return + this.options.backdrop == 'static' + ? this.$element[0].focus.call(this.$element[0]) + : this.hide.call(this) + }, this)) if (doAnimate) this.$backdrop[0].offsetWidth // force reflow @@ -1001,7 +1101,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re doAnimate ? this.$backdrop .one('bsTransitionEnd', callback) - .emulateTransitionEnd(150) : + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callback() } else if (!this.isShown && this.$backdrop) { @@ -1014,7 +1114,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re $.support.transition && this.$element.hasClass('fade') ? this.$backdrop .one('bsTransitionEnd', callbackRemove) - .emulateTransitionEnd(150) : + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callbackRemove() } else if (callback) { @@ -1022,14 +1122,43 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re } } + // these following methods are used to handle overflowing modals + + Modal.prototype.handleUpdate = function () { + if (this.options.backdrop) this.adjustBackdrop() + this.adjustDialog() + } + + Modal.prototype.adjustBackdrop = function () { + this.$backdrop + .css('height', 0) + .css('height', this.$element[0].scrollHeight) + } + + Modal.prototype.adjustDialog = function () { + var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight + + this.$element.css({ + paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', + paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' + }) + } + + Modal.prototype.resetAdjustments = function () { + this.$element.css({ + paddingLeft: '', + paddingRight: '' + }) + } + Modal.prototype.checkScrollbar = function () { - if (document.body.clientWidth >= window.innerWidth) return - this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar() + this.bodyIsOverflowing = document.body.scrollHeight > document.documentElement.clientHeight + this.scrollbarWidth = this.measureScrollbar() } Modal.prototype.setScrollbar = function () { var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) - if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) + if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) } Modal.prototype.resetScrollbar = function () { @@ -1099,7 +1228,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re }(jQuery); /* ======================================================================== - * Bootstrap: tooltip.js v3.2.0 + * Bootstrap: tooltip.js v3.3.1 * http://getbootstrap.com/javascript/#tooltip * Inspired by the original jQuery.tipsy by Jason Frame * ======================================================================== @@ -1125,7 +1254,9 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re this.init('tooltip', element, options) } - Tooltip.VERSION = '3.2.0' + Tooltip.VERSION = '3.3.1' + + Tooltip.TRANSITION_DURATION = 150 Tooltip.DEFAULTS = { animation: true, @@ -1203,6 +1334,11 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re var self = obj instanceof this.constructor ? obj : $(obj.currentTarget).data('bs.' + this.type) + if (self && self.$tip && self.$tip.is(':visible')) { + self.hoverState = 'in' + return + } + if (!self) { self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) $(obj.currentTarget).data('bs.' + this.type, self) @@ -1245,7 +1381,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re if (this.hasContent() && this.enabled) { this.$element.trigger(e) - var inDom = $.contains(document.documentElement, this.$element[0]) + var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) if (e.isDefaultPrevented() || !inDom) return var that = this @@ -1281,13 +1417,13 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re if (autoPlace) { var orgPlacement = placement - var $parent = this.$element.parent() - var parentDim = this.getPosition($parent) + var $container = this.options.container ? $(this.options.container) : this.$element.parent() + var containerDim = this.getPosition($container) - placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' : - placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' : - placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' : - placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : + placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' : + placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' : + placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' : + placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' : placement $tip @@ -1300,14 +1436,17 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re this.applyPlacement(calculatedOffset, placement) var complete = function () { + var prevHoverState = that.hoverState that.$element.trigger('shown.bs.' + that.type) that.hoverState = null + + if (prevHoverState == 'out') that.leave(that) } $.support.transition && this.$tip.hasClass('fade') ? $tip .one('bsTransitionEnd', complete) - .emulateTransitionEnd(150) : + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete() } } @@ -1354,16 +1493,18 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re if (delta.left) offset.left += delta.left else offset.top += delta.top - var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight - var arrowPosition = delta.left ? 'left' : 'top' - var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' + var isVertical = /top|bottom/.test(placement) + var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight + var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' $tip.offset(offset) - this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) + this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) } - Tooltip.prototype.replaceArrow = function (delta, dimension, position) { - this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') + Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) { + this.arrow() + .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') + .css(isHorizontal ? 'top' : 'left', '') } Tooltip.prototype.setContent = function () { @@ -1374,16 +1515,17 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re $tip.removeClass('fade in top bottom left right') } - Tooltip.prototype.hide = function () { + Tooltip.prototype.hide = function (callback) { var that = this var $tip = this.tip() var e = $.Event('hide.bs.' + this.type) - this.$element.removeAttr('aria-describedby') - function complete() { if (that.hoverState != 'in') $tip.detach() - that.$element.trigger('hidden.bs.' + that.type) + that.$element + .removeAttr('aria-describedby') + .trigger('hidden.bs.' + that.type) + callback && callback() } this.$element.trigger(e) @@ -1395,7 +1537,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re $.support.transition && this.$tip.hasClass('fade') ? $tip .one('bsTransitionEnd', complete) - .emulateTransitionEnd(150) : + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete() this.hoverState = null @@ -1416,13 +1558,20 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re Tooltip.prototype.getPosition = function ($element) { $element = $element || this.$element + var el = $element[0] var isBody = el.tagName == 'BODY' - return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, { - scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(), - width: isBody ? $(window).width() : $element.outerWidth(), - height: isBody ? $(window).height() : $element.outerHeight() - }, isBody ? { top: 0, left: 0 } : $element.offset()) + + var elRect = el.getBoundingClientRect() + if (elRect.width == null) { + // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 + elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) + } + var elOffset = isBody ? { top: 0, left: 0 } : $element.offset() + var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } + var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null + + return $.extend({}, elRect, scroll, outerDims, elOffset) } Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { @@ -1486,14 +1635,6 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) } - Tooltip.prototype.validate = function () { - if (!this.$element[0].parentNode) { - this.hide() - this.$element = null - this.options = null - } - } - Tooltip.prototype.enable = function () { this.enabled = true } @@ -1520,8 +1661,11 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re } Tooltip.prototype.destroy = function () { + var that = this clearTimeout(this.timeout) - this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) + this.hide(function () { + that.$element.off('.' + that.type).removeData('bs.' + that.type) + }) } @@ -1530,12 +1674,18 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re function Plugin(option) { return this.each(function () { - var $this = $(this) - var data = $this.data('bs.tooltip') - var options = typeof option == 'object' && option + var $this = $(this) + var data = $this.data('bs.tooltip') + var options = typeof option == 'object' && option + var selector = options && options.selector if (!data && option == 'destroy') return - if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) + if (selector) { + if (!data) $this.data('bs.tooltip', (data = {})) + if (!data[selector]) data[selector] = new Tooltip(this, options) + } else { + if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) + } if (typeof option == 'string') data[option]() }) } @@ -1557,7 +1707,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re }(jQuery); /* ======================================================================== - * Bootstrap: popover.js v3.2.0 + * Bootstrap: popover.js v3.3.1 * http://getbootstrap.com/javascript/#popovers * ======================================================================== * Copyright 2011-2014 Twitter, Inc. @@ -1577,7 +1727,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') - Popover.VERSION = '3.2.0' + Popover.VERSION = '3.3.1' Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { placement: 'right', @@ -1604,7 +1754,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re var content = this.getContent() $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) - $tip.find('.popover-content').empty()[ // we use append for html objects to maintain js events + $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' ](content) @@ -1644,12 +1794,18 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re function Plugin(option) { return this.each(function () { - var $this = $(this) - var data = $this.data('bs.popover') - var options = typeof option == 'object' && option + var $this = $(this) + var data = $this.data('bs.popover') + var options = typeof option == 'object' && option + var selector = options && options.selector if (!data && option == 'destroy') return - if (!data) $this.data('bs.popover', (data = new Popover(this, options))) + if (selector) { + if (!data) $this.data('bs.popover', (data = {})) + if (!data[selector]) data[selector] = new Popover(this, options) + } else { + if (!data) $this.data('bs.popover', (data = new Popover(this, options))) + } if (typeof option == 'string') data[option]() }) } @@ -1671,7 +1827,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re }(jQuery); /* ======================================================================== - * Bootstrap: scrollspy.js v3.2.0 + * Bootstrap: scrollspy.js v3.3.1 * http://getbootstrap.com/javascript/#scrollspy * ======================================================================== * Copyright 2011-2014 Twitter, Inc. @@ -1702,7 +1858,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re this.process() } - ScrollSpy.VERSION = '3.2.0' + ScrollSpy.VERSION = '3.3.1' ScrollSpy.DEFAULTS = { offset: 10 @@ -1763,8 +1919,9 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) } - if (activeTarget && scrollTop <= offsets[0]) { - return activeTarget != (i = targets[0]) && this.activate(i) + if (activeTarget && scrollTop < offsets[0]) { + this.activeTarget = null + return this.clear() } for (i = offsets.length; i--;) { @@ -1778,9 +1935,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re ScrollSpy.prototype.activate = function (target) { this.activeTarget = target - $(this.selector) - .parentsUntil(this.options.target, '.active') - .removeClass('active') + this.clear() var selector = this.selector + '[data-target="' + target + '"],' + @@ -1799,6 +1954,12 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re active.trigger('activate.bs.scrollspy') } + ScrollSpy.prototype.clear = function () { + $(this.selector) + .parentsUntil(this.options.target, '.active') + .removeClass('active') + } + // SCROLLSPY PLUGIN DEFINITION // =========================== @@ -1842,7 +2003,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re }(jQuery); /* ======================================================================== - * Bootstrap: tab.js v3.2.0 + * Bootstrap: tab.js v3.3.1 * http://getbootstrap.com/javascript/#tabs * ======================================================================== * Copyright 2011-2014 Twitter, Inc. @@ -1860,7 +2021,9 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re this.element = $(element) } - Tab.VERSION = '3.2.0' + Tab.VERSION = '3.3.1' + + Tab.TRANSITION_DURATION = 150 Tab.prototype.show = function () { var $this = this.element @@ -1874,22 +2037,30 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re if ($this.parent('li').hasClass('active')) return - var previous = $ul.find('.active:last a')[0] - var e = $.Event('show.bs.tab', { - relatedTarget: previous + var $previous = $ul.find('.active:last a') + var hideEvent = $.Event('hide.bs.tab', { + relatedTarget: $this[0] + }) + var showEvent = $.Event('show.bs.tab', { + relatedTarget: $previous[0] }) - $this.trigger(e) + $previous.trigger(hideEvent) + $this.trigger(showEvent) - if (e.isDefaultPrevented()) return + if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return var $target = $(selector) this.activate($this.closest('li'), $ul) this.activate($target, $target.parent(), function () { + $previous.trigger({ + type: 'hidden.bs.tab', + relatedTarget: $this[0] + }) $this.trigger({ type: 'shown.bs.tab', - relatedTarget: previous + relatedTarget: $previous[0] }) }) } @@ -1898,15 +2069,21 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re var $active = container.find('> .active') var transition = callback && $.support.transition - && $active.hasClass('fade') + && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length) function next() { $active .removeClass('active') .find('> .dropdown-menu > .active') - .removeClass('active') + .removeClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', false) - element.addClass('active') + element + .addClass('active') + .find('[data-toggle="tab"]') + .attr('aria-expanded', true) if (transition) { element[0].offsetWidth // reflow for transition @@ -1916,16 +2093,21 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re } if (element.parent('.dropdown-menu')) { - element.closest('li.dropdown').addClass('active') + element + .closest('li.dropdown') + .addClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', true) } callback && callback() } - transition ? + $active.length && transition ? $active .one('bsTransitionEnd', next) - .emulateTransitionEnd(150) : + .emulateTransitionEnd(Tab.TRANSITION_DURATION) : next() $active.removeClass('in') @@ -1963,15 +2145,19 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re // TAB DATA-API // ============ - $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { + var clickHandler = function (e) { e.preventDefault() Plugin.call($(this), 'show') - }) + } + + $(document) + .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) + .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) }(jQuery); /* ======================================================================== - * Bootstrap: affix.js v3.2.0 + * Bootstrap: affix.js v3.3.1 * http://getbootstrap.com/javascript/#affix * ======================================================================== * Copyright 2011-2014 Twitter, Inc. @@ -2000,7 +2186,7 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re this.checkPosition() } - Affix.VERSION = '3.2.0' + Affix.VERSION = '3.3.1' Affix.RESET = 'affix affix-top affix-bottom' @@ -2009,6 +2195,28 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re target: window } + Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { + var scrollTop = this.$target.scrollTop() + var position = this.$element.offset() + var targetHeight = this.$target.height() + + if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false + + if (this.affixed == 'bottom') { + if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' + return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' + } + + var initializing = this.affixed == null + var colliderTop = initializing ? scrollTop : position.top + var colliderHeight = initializing ? targetHeight : height + + if (offsetTop != null && colliderTop <= offsetTop) return 'top' + if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' + + return false + } + Affix.prototype.getPinnedOffset = function () { if (this.pinnedOffset) return this.pinnedOffset this.$element.removeClass(Affix.RESET).addClass('affix') @@ -2024,42 +2232,40 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re Affix.prototype.checkPosition = function () { if (!this.$element.is(':visible')) return - var scrollHeight = $(document).height() - var scrollTop = this.$target.scrollTop() - var position = this.$element.offset() + var height = this.$element.height() var offset = this.options.offset var offsetTop = offset.top var offsetBottom = offset.bottom + var scrollHeight = $('body').height() if (typeof offset != 'object') offsetBottom = offsetTop = offset if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) - var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false : - offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' : - offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false + var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) - if (this.affixed === affix) return - if (this.unpin != null) this.$element.css('top', '') + if (this.affixed != affix) { + if (this.unpin != null) this.$element.css('top', '') - var affixType = 'affix' + (affix ? '-' + affix : '') - var e = $.Event(affixType + '.bs.affix') + var affixType = 'affix' + (affix ? '-' + affix : '') + var e = $.Event(affixType + '.bs.affix') - this.$element.trigger(e) + this.$element.trigger(e) - if (e.isDefaultPrevented()) return + if (e.isDefaultPrevented()) return - this.affixed = affix - this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null + this.affixed = affix + this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null - this.$element - .removeClass(Affix.RESET) - .addClass(affixType) - .trigger($.Event(affixType.replace('affix', 'affixed'))) + this.$element + .removeClass(Affix.RESET) + .addClass(affixType) + .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') + } if (affix == 'bottom') { this.$element.offset({ - top: scrollHeight - this.$element.height() - offsetBottom + top: scrollHeight - height - offsetBottom }) } } @@ -2104,8 +2310,8 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re data.offset = data.offset || {} - if (data.offsetBottom) data.offset.bottom = data.offsetBottom - if (data.offsetTop) data.offset.top = data.offsetTop + if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom + if (data.offsetTop != null) data.offset.top = data.offsetTop Plugin.call($spy, data) }) diff --git a/web/src/vendor/bootstrap/glyphicons-halflings-regular.svg b/web/src/vendor/bootstrap/glyphicons-halflings-regular.svg index e3e2dc73..25691af8 100644 --- a/web/src/vendor/bootstrap/glyphicons-halflings-regular.svg +++ b/web/src/vendor/bootstrap/glyphicons-halflings-regular.svg @@ -226,4 +226,4 @@ <glyph unicode="" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" /> <glyph unicode="" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -11.5t1 -11.5q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" /> </font> -</defs></svg>
\ No newline at end of file +</defs></svg>
\ No newline at end of file diff --git a/web/src/vendor/qunit/qunit.css b/web/src/vendor/qunit/qunit.css index 9437b4b6..385a1ce0 100644 --- a/web/src/vendor/qunit/qunit.css +++ b/web/src/vendor/qunit/qunit.css @@ -1,12 +1,12 @@ /*! - * QUnit 1.15.0 + * QUnit 1.16.0 * http://qunitjs.com/ * - * Copyright 2014 jQuery Foundation and other contributors + * Copyright 2006, 2014 jQuery Foundation and other contributors * Released under the MIT license * http://jquery.org/license * - * Date: 2014-08-08T16:00Z + * Date: 2014-12-03T16:32Z */ /** Font Family and Sizes */ @@ -91,6 +91,14 @@ list-style-position: inside; } +#qunit-tests > li { + display: none; +} + +#qunit-tests li.pass, #qunit-tests li.running, #qunit-tests li.fail { + display: list-item; +} + #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { display: none; } @@ -99,6 +107,10 @@ cursor: pointer; } +#qunit-tests li.skipped strong { + cursor: default; +} + #qunit-tests li a { padding: 0.5em; color: #C2CCD1; @@ -211,6 +223,21 @@ #qunit-banner.qunit-fail { background-color: #EE5757; } +/*** Skipped tests */ + +#qunit-tests .skipped { + background-color: #EBECE9; +} + +#qunit-tests .qunit-skipped-label { + background-color: #F4FF77; + display: inline-block; + font-style: normal; + color: #366097; + line-height: 1.8em; + padding: 0 0.5em; + margin: -0.4em 0.4em -0.4em 0; +} /** Result */ diff --git a/web/src/vendor/qunit/qunit.js b/web/src/vendor/qunit/qunit.js index 474cfe55..82020d40 100644 --- a/web/src/vendor/qunit/qunit.js +++ b/web/src/vendor/qunit/qunit.js @@ -1,12 +1,12 @@ /*! - * QUnit 1.15.0 + * QUnit 1.16.0 * http://qunitjs.com/ * - * Copyright 2014 jQuery Foundation and other contributors + * Copyright 2006, 2014 jQuery Foundation and other contributors * Released under the MIT license * http://jquery.org/license * - * Date: 2014-08-08T16:00Z + * Date: 2014-12-03T16:32Z */ (function( window ) { @@ -14,6 +14,7 @@ var QUnit, config, onErrorFnPrev, + loggingCallbacks = {}, fileName = ( sourceFromStacktrace( 0 ) || "" ).replace( /(:\d+)+\)?/, "" ).replace( /.+\//, "" ), toString = Object.prototype.toString, hasOwn = Object.prototype.hasOwnProperty, @@ -22,11 +23,13 @@ var QUnit, now = Date.now || function() { return new Date().getTime(); }, + globalStartCalled = false, + runStarted = false, setTimeout = window.setTimeout, clearTimeout = window.clearTimeout, defined = { - document: typeof window.document !== "undefined", - setTimeout: typeof window.setTimeout !== "undefined", + document: window.document !== undefined, + setTimeout: window.setTimeout !== undefined, sessionStorage: (function() { var x = "qunit-test-string"; try { @@ -86,132 +89,7 @@ var QUnit, return vals; }; -// Root QUnit object. -// `QUnit` initialized at top of scope -QUnit = { - - // call on start of module test to prepend name to all tests - module: function( name, testEnvironment ) { - config.currentModule = name; - config.currentModuleTestEnvironment = testEnvironment; - config.modules[ name ] = true; - }, - - asyncTest: function( testName, expected, callback ) { - if ( arguments.length === 2 ) { - callback = expected; - expected = null; - } - - QUnit.test( testName, expected, callback, true ); - }, - - test: function( testName, expected, callback, async ) { - var test; - - if ( arguments.length === 2 ) { - callback = expected; - expected = null; - } - - test = new Test({ - testName: testName, - expected: expected, - async: async, - callback: callback, - module: config.currentModule, - moduleTestEnvironment: config.currentModuleTestEnvironment, - stack: sourceFromStacktrace( 2 ) - }); - - if ( !validTest( test ) ) { - return; - } - - test.queue(); - }, - - start: function( count ) { - var message; - - // QUnit hasn't been initialized yet. - // Note: RequireJS (et al) may delay onLoad - if ( config.semaphore === undefined ) { - QUnit.begin(function() { - // This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first - setTimeout(function() { - QUnit.start( count ); - }); - }); - return; - } - - config.semaphore -= count || 1; - // don't start until equal number of stop-calls - if ( config.semaphore > 0 ) { - return; - } - - // Set the starting time when the first test is run - QUnit.config.started = QUnit.config.started || now(); - // ignore if start is called more often then stop - if ( config.semaphore < 0 ) { - config.semaphore = 0; - - message = "Called start() while already started (QUnit.config.semaphore was 0 already)"; - - if ( config.current ) { - QUnit.pushFailure( message, sourceFromStacktrace( 2 ) ); - } else { - throw new Error( message ); - } - - return; - } - // A slight delay, to avoid any current callbacks - if ( defined.setTimeout ) { - setTimeout(function() { - if ( config.semaphore > 0 ) { - return; - } - if ( config.timeout ) { - clearTimeout( config.timeout ); - } - - config.blocking = false; - process( true ); - }, 13 ); - } else { - config.blocking = false; - process( true ); - } - }, - - stop: function( count ) { - config.semaphore += count || 1; - config.blocking = true; - - if ( config.testTimeout && defined.setTimeout ) { - clearTimeout( config.timeout ); - config.timeout = setTimeout(function() { - QUnit.ok( false, "Test timed out" ); - config.semaphore = 1; - QUnit.start(); - }, config.testTimeout ); - } - } -}; - -// We use the prototype to distinguish between properties that should -// be exposed as globals (and in exports) and those that shouldn't -(function() { - function F() {} - F.prototype = QUnit; - QUnit = new F(); - - // Make F QUnit's constructor so that we can add to the prototype later - QUnit.constructor = F; -}()); +QUnit = {}; /** * Config object: Maintain internal state @@ -246,23 +124,39 @@ config = { // when enabled, the id is set to `true` as a `QUnit.config` property urlConfig: [ { + id: "hidepassed", + label: "Hide passed tests", + tooltip: "Only show tests and assertions that fail. Stored as query-strings." + }, + { id: "noglobals", label: "Check for Globals", - tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings." + tooltip: "Enabling this will test if any test introduces new properties on the " + + "`window` object. Stored as query-strings." }, { id: "notrycatch", label: "No try-catch", - tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings." + tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging " + + "exceptions in IE reasonable. Stored as query-strings." } ], // Set of all modules. - modules: {}, + modules: [], + + // The first unnamed module + currentModule: { + name: "", + tests: [] + }, callbacks: {} }; +// Push a loose unnamed module to the modules collection +config.modules.push( config.currentModule ); + // Initialize more QUnit.config and QUnit.urlParams (function() { var i, current, @@ -291,17 +185,13 @@ config = { // String search anywhere in moduleName+testName config.filter = urlParams.filter; - // Exact match of the module name - config.module = urlParams.module; - - config.testNumber = []; - if ( urlParams.testNumber ) { + config.testId = []; + if ( urlParams.testId ) { - // Ensure that urlParams.testNumber is an array - urlParams.testNumber = [].concat( urlParams.testNumber ); - for ( i = 0; i < urlParams.testNumber.length; i++ ) { - current = urlParams.testNumber[ i ]; - config.testNumber.push( parseInt( current, 10 ) ); + // Ensure that urlParams.testId is an array + urlParams.testId = [].concat( urlParams.testId ); + for ( i = 0; i < urlParams.testId.length; i++ ) { + config.testId.push( urlParams.testId[ i ] ); } } @@ -309,8 +199,130 @@ config = { QUnit.isLocal = location.protocol === "file:"; }()); +// Root QUnit object. +// `QUnit` initialized at top of scope extend( QUnit, { + // call on start of module test to prepend name to all tests + module: function( name, testEnvironment ) { + var currentModule = { + name: name, + testEnvironment: testEnvironment, + tests: [] + }; + + // DEPRECATED: handles setup/teardown functions, + // beforeEach and afterEach should be used instead + if ( testEnvironment && testEnvironment.setup ) { + testEnvironment.beforeEach = testEnvironment.setup; + delete testEnvironment.setup; + } + if ( testEnvironment && testEnvironment.teardown ) { + testEnvironment.afterEach = testEnvironment.teardown; + delete testEnvironment.teardown; + } + + config.modules.push( currentModule ); + config.currentModule = currentModule; + }, + + // DEPRECATED: QUnit.asyncTest() will be removed in QUnit 2.0. + asyncTest: function( testName, expected, callback ) { + if ( arguments.length === 2 ) { + callback = expected; + expected = null; + } + + QUnit.test( testName, expected, callback, true ); + }, + + test: function( testName, expected, callback, async ) { + var test; + + if ( arguments.length === 2 ) { + callback = expected; + expected = null; + } + + test = new Test({ + testName: testName, + expected: expected, + async: async, + callback: callback + }); + + test.queue(); + }, + + skip: function( testName ) { + var test = new Test({ + testName: testName, + skip: true + }); + + test.queue(); + }, + + // DEPRECATED: The functionality of QUnit.start() will be altered in QUnit 2.0. + // In QUnit 2.0, invoking it will ONLY affect the `QUnit.config.autostart` blocking behavior. + start: function( count ) { + var globalStartAlreadyCalled = globalStartCalled; + + if ( !config.current ) { + globalStartCalled = true; + + if ( runStarted ) { + throw new Error( "Called start() outside of a test context while already started" ); + } else if ( globalStartAlreadyCalled || count > 1 ) { + throw new Error( "Called start() outside of a test context too many times" ); + } else if ( config.autostart ) { + throw new Error( "Called start() outside of a test context when " + + "QUnit.config.autostart was true" ); + } else if ( !config.pageLoaded ) { + + // The page isn't completely loaded yet, so bail out and let `QUnit.load` handle it + config.autostart = true; + return; + } + } else { + + // If a test is running, adjust its semaphore + config.current.semaphore -= count || 1; + + // Don't start until equal number of stop-calls + if ( config.current.semaphore > 0 ) { + return; + } + + // throw an Error if start is called more often than stop + if ( config.current.semaphore < 0 ) { + config.current.semaphore = 0; + + QUnit.pushFailure( + "Called start() while already started (test's semaphore was 0 already)", + sourceFromStacktrace( 2 ) + ); + return; + } + } + + resumeProcessing(); + }, + + // DEPRECATED: QUnit.stop() will be removed in QUnit 2.0. + stop: function( count ) { + + // If there isn't a test running, don't allow QUnit.stop() to be called + if ( !config.current ) { + throw new Error( "Called stop() outside of a test context" ); + } + + // If a test is running, adjust its semaphore + config.current.semaphore += count || 1; + + pauseProcessing(); + }, + config: config, // Safe object type checking @@ -358,71 +370,76 @@ extend( QUnit, { for ( key in params ) { if ( hasOwn.call( params, key ) ) { - querystring += encodeURIComponent( key ) + "=" + - encodeURIComponent( params[ key ] ) + "&"; + querystring += encodeURIComponent( key ); + if ( params[ key ] !== true ) { + querystring += "=" + encodeURIComponent( params[ key ] ); + } + querystring += "&"; } } - return window.location.protocol + "//" + window.location.host + - window.location.pathname + querystring.slice( 0, -1 ); + return location.protocol + "//" + location.host + + location.pathname + querystring.slice( 0, -1 ); }, - extend: extend -}); - -/** - * @deprecated: Created for backwards compatibility with test runner that set the hook function - * into QUnit.{hook}, instead of invoking it and passing the hook function. - * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here. - * Doing this allows us to tell if the following methods have been overwritten on the actual - * QUnit object. - */ -extend( QUnit.constructor.prototype, { + extend: extend, - // Logging callbacks; all receive a single argument with the listed properties - // run test/logs.html for any related changes - begin: registerLoggingCallback( "begin" ), + load: function() { + config.pageLoaded = true; - // done: { failed, passed, total, runtime } - done: registerLoggingCallback( "done" ), + // Initialize the configuration options + extend( config, { + stats: { all: 0, bad: 0 }, + moduleStats: { all: 0, bad: 0 }, + started: 0, + updateRate: 1000, + autostart: true, + filter: "" + }, true ); - // log: { result, actual, expected, message } - log: registerLoggingCallback( "log" ), + config.blocking = false; - // testStart: { name } - testStart: registerLoggingCallback( "testStart" ), + if ( config.autostart ) { + resumeProcessing(); + } + } +}); - // testDone: { name, failed, passed, total, runtime } - testDone: registerLoggingCallback( "testDone" ), +// Register logging callbacks +(function() { + var i, l, key, + callbacks = [ "begin", "done", "log", "testStart", "testDone", + "moduleStart", "moduleDone" ]; + + function registerLoggingCallback( key ) { + var loggingCallback = function( callback ) { + if ( QUnit.objectType( callback ) !== "function" ) { + throw new Error( + "QUnit logging methods require a callback function as their first parameters." + ); + } - // moduleStart: { name } - moduleStart: registerLoggingCallback( "moduleStart" ), + config.callbacks[ key ].push( callback ); + }; - // moduleDone: { name, failed, passed, total } - moduleDone: registerLoggingCallback( "moduleDone" ) -}); + // DEPRECATED: This will be removed on QUnit 2.0.0+ + // Stores the registered functions allowing restoring + // at verifyLoggingCallbacks() if modified + loggingCallbacks[ key ] = loggingCallback; -QUnit.load = function() { - runLoggingCallbacks( "begin", { - totalTests: Test.count - }); + return loggingCallback; + } - // Initialize the configuration options - extend( config, { - stats: { all: 0, bad: 0 }, - moduleStats: { all: 0, bad: 0 }, - started: 0, - updateRate: 1000, - autostart: true, - filter: "", - semaphore: 1 - }, true ); + for ( i = 0, l = callbacks.length; i < l; i++ ) { + key = callbacks[ i ]; - config.blocking = false; + // Initialize key collection of logging callback + if ( QUnit.objectType( config.callbacks[ key ] ) === "undefined" ) { + config.callbacks[ key ] = []; + } - if ( config.autostart ) { - QUnit.start(); + QUnit[ key ] = registerLoggingCallback( key ); } -}; +})(); // `onErrorFnPrev` initialized at top of scope // Preserve other handlers @@ -448,7 +465,7 @@ window.onerror = function( error, filePath, linerNr ) { } else { QUnit.test( "global failure", extend(function() { QUnit.pushFailure( error, filePath + ":" + linerNr ); - }, { validTest: validTest } ) ); + }, { validTest: true } ) ); } return false; } @@ -457,21 +474,25 @@ window.onerror = function( error, filePath, linerNr ) { }; function done() { + var runtime, passed; + config.autorun = true; // Log the last module results if ( config.previousModule ) { runLoggingCallbacks( "moduleDone", { - name: config.previousModule, + name: config.previousModule.name, + tests: config.previousModule.tests, failed: config.moduleStats.bad, passed: config.moduleStats.all - config.moduleStats.bad, - total: config.moduleStats.all + total: config.moduleStats.all, + runtime: now() - config.moduleStats.started }); } delete config.previousModule; - var runtime = now() - config.started, - passed = config.stats.all - config.stats.bad; + runtime = now() - config.started; + passed = config.stats.all - config.stats.bad; runLoggingCallbacks( "done", { failed: config.stats.bad, @@ -481,47 +502,6 @@ function done() { }); } -/** @return Boolean: true if this test should be ran */ -function validTest( test ) { - var include, - filter = config.filter && config.filter.toLowerCase(), - module = config.module && config.module.toLowerCase(), - fullName = ( test.module + ": " + test.testName ).toLowerCase(); - - // Internally-generated tests are always valid - if ( test.callback && test.callback.validTest === validTest ) { - delete test.callback.validTest; - return true; - } - - if ( config.testNumber.length > 0 ) { - if ( inArray( test.testNumber, config.testNumber ) < 0 ) { - return false; - } - } - - if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) { - return false; - } - - if ( !filter ) { - return true; - } - - include = filter.charAt( 0 ) !== "!"; - if ( !include ) { - filter = filter.slice( 1 ); - } - - // If the filter matches, we need to honour include - if ( fullName.indexOf( filter ) !== -1 ) { - return include; - } - - // Otherwise, do the opposite - return !include; -} - // Doesn't support IE6 to IE9 // See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack function extractStacktrace( e, offset ) { @@ -565,15 +545,27 @@ function extractStacktrace( e, offset ) { return e.sourceURL + ":" + e.line; } } + function sourceFromStacktrace( offset ) { - try { - throw new Error(); - } catch ( e ) { - return extractStacktrace( e, offset ); + var e = new Error(); + if ( !e.stack ) { + try { + throw e; + } catch ( err ) { + // This should already be true in most browsers + e = err; + } } + return extractStacktrace( e, offset ); } function synchronize( callback, last ) { + if ( QUnit.objectType( callback ) === "array" ) { + while ( callback.length ) { + synchronize( callback.shift() ); + } + return; + } config.queue.push( callback ); if ( config.autorun && !config.blocking ) { @@ -589,7 +581,13 @@ function process( last ) { config.depth = config.depth ? config.depth + 1 : 1; while ( config.queue.length && !config.blocking ) { - if ( !defined.setTimeout || config.updateRate <= 0 || ( ( now() - start ) < config.updateRate ) ) { + if ( !defined.setTimeout || config.updateRate <= 0 || + ( ( now() - start ) < config.updateRate ) ) { + if ( config.current ) { + + // Reset async tracking for each phase of the Test lifecycle + config.current.usedAsync = false; + } config.queue.shift()(); } else { setTimeout( next, 13 ); @@ -602,6 +600,79 @@ function process( last ) { } } +function begin() { + var i, l, + modulesLog = []; + + // If the test run hasn't officially begun yet + if ( !config.started ) { + + // Record the time of the test run's beginning + config.started = now(); + + verifyLoggingCallbacks(); + + // Delete the loose unnamed module if unused. + if ( config.modules[ 0 ].name === "" && config.modules[ 0 ].tests.length === 0 ) { + config.modules.shift(); + } + + // Avoid unnecessary information by not logging modules' test environments + for ( i = 0, l = config.modules.length; i < l; i++ ) { + modulesLog.push({ + name: config.modules[ i ].name, + tests: config.modules[ i ].tests + }); + } + + // The test run is officially beginning now + runLoggingCallbacks( "begin", { + totalTests: Test.count, + modules: modulesLog + }); + } + + config.blocking = false; + process( true ); +} + +function resumeProcessing() { + runStarted = true; + + // A slight delay to allow this iteration of the event loop to finish (more assertions, etc.) + if ( defined.setTimeout ) { + setTimeout(function() { + if ( config.current && config.current.semaphore > 0 ) { + return; + } + if ( config.timeout ) { + clearTimeout( config.timeout ); + } + + begin(); + }, 13 ); + } else { + begin(); + } +} + +function pauseProcessing() { + config.blocking = true; + + if ( config.testTimeout && defined.setTimeout ) { + clearTimeout( config.timeout ); + config.timeout = setTimeout(function() { + if ( config.current ) { + config.current.semaphore = 0; + QUnit.pushFailure( "Test timed out", sourceFromStacktrace( 2 ) ); + } else { + throw new Error( "Test timed out" ); + } + resumeProcessing(); + }, config.testTimeout ); + } +} + function saveGlobal() { config.pollution = []; @@ -671,18 +742,6 @@ function extend( a, b, undefOnly ) { return a; } -function registerLoggingCallback( key ) { - - // Initialize key collection of logging callback - if ( QUnit.objectType( config.callbacks[ key ] ) === "undefined" ) { - config.callbacks[ key ] = []; - } - - return function( callback ) { - config.callbacks[ key ].push( callback ); - }; -} - function runLoggingCallbacks( key, args ) { var i, l, callbacks; @@ -692,6 +751,34 @@ function runLoggingCallbacks( key, args ) { } } +// DEPRECATED: This will be removed on 2.0.0+ +// This function verifies if the loggingCallbacks were modified by the user +// If so, it will restore it, assign the given callback and print a console warning +function verifyLoggingCallbacks() { + var loggingCallback, userCallback; + + for ( loggingCallback in loggingCallbacks ) { + if ( QUnit[ loggingCallback ] !== loggingCallbacks[ loggingCallback ] ) { + + userCallback = QUnit[ loggingCallback ]; + + // Restore the callback function + QUnit[ loggingCallback ] = loggingCallbacks[ loggingCallback ]; + + // Assign the deprecated given callback + QUnit[ loggingCallback ]( userCallback ); + + if ( window.console && window.console.warn ) { + window.console.warn( + "QUnit." + loggingCallback + " was replaced with a new value.\n" + + "Please, check out the documentation on how to apply logging callbacks.\n" + + "Reference: http://api.qunitjs.com/category/callbacks/" + ); + } + } + } +} + // from jquery.js function inArray( elem, array ) { if ( array.indexOf ) { @@ -708,16 +795,46 @@ function inArray( elem, array ) { } function Test( settings ) { + var i, l; + + ++Test.count; + extend( this, settings ); - this.assert = new Assert( this ); this.assertions = []; - this.testNumber = ++Test.count; + this.semaphore = 0; + this.usedAsync = false; + this.module = config.currentModule; + this.stack = sourceFromStacktrace( 3 ); + + // Register unique strings + for ( i = 0, l = this.module.tests; i < l.length; i++ ) { + if ( this.module.tests[ i ].name === this.testName ) { + this.testName += " "; + } + } + + this.testId = generateHash( this.module.name, this.testName ); + + this.module.tests.push({ + name: this.testName, + testId: this.testId + }); + + if ( settings.skip ) { + + // Skipped tests will fully ignore any sent callback + this.callback = function() {}; + this.async = false; + this.expected = 0; + } else { + this.assert = new Assert( this ); + } } Test.count = 0; Test.prototype = { - setup: function() { + before: function() { if ( // Emit moduleStart when we're switching from one module to another @@ -731,47 +848,43 @@ Test.prototype = { ) { if ( hasOwn.call( config, "previousModule" ) ) { runLoggingCallbacks( "moduleDone", { - name: config.previousModule, + name: config.previousModule.name, + tests: config.previousModule.tests, failed: config.moduleStats.bad, passed: config.moduleStats.all - config.moduleStats.bad, - total: config.moduleStats.all + total: config.moduleStats.all, + runtime: now() - config.moduleStats.started }); } config.previousModule = this.module; - config.moduleStats = { all: 0, bad: 0 }; + config.moduleStats = { all: 0, bad: 0, started: now() }; runLoggingCallbacks( "moduleStart", { - name: this.module + name: this.module.name, + tests: this.module.tests }); } config.current = this; - this.testEnvironment = extend({ - setup: function() {}, - teardown: function() {} - }, this.moduleTestEnvironment ); + this.testEnvironment = extend( {}, this.module.testEnvironment ); + delete this.testEnvironment.beforeEach; + delete this.testEnvironment.afterEach; this.started = now(); runLoggingCallbacks( "testStart", { name: this.testName, - module: this.module, - testNumber: this.testNumber + module: this.module.name, + testId: this.testId }); if ( !config.pollution ) { saveGlobal(); } - if ( config.notrycatch ) { - this.testEnvironment.setup.call( this.testEnvironment, this.assert ); - return; - } - try { - this.testEnvironment.setup.call( this.testEnvironment, this.assert ); - } catch ( e ) { - this.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 0 ) ); - } }, + run: function() { + var promise; + config.current = this; if ( this.async ) { @@ -781,18 +894,17 @@ Test.prototype = { this.callbackStarted = now(); if ( config.notrycatch ) { - this.callback.call( this.testEnvironment, this.assert ); - this.callbackRuntime = now() - this.callbackStarted; + promise = this.callback.call( this.testEnvironment, this.assert ); + this.resolvePromise( promise ); return; } try { - this.callback.call( this.testEnvironment, this.assert ); - this.callbackRuntime = now() - this.callbackStarted; + promise = this.callback.call( this.testEnvironment, this.assert ); + this.resolvePromise( promise ); } catch ( e ) { - this.callbackRuntime = now() - this.callbackStarted; - - this.pushFailure( "Died on test #" + ( this.assertions.length + 1 ) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) ); + this.pushFailure( "Died on test #" + ( this.assertions.length + 1 ) + " " + + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) ); // else next test will carry the responsibility saveGlobal(); @@ -803,31 +915,59 @@ Test.prototype = { } } }, - teardown: function() { - config.current = this; - if ( config.notrycatch ) { - if ( typeof this.callbackRuntime === "undefined" ) { - this.callbackRuntime = now() - this.callbackStarted; + + after: function() { + checkPollution(); + }, + + queueHook: function( hook, hookName ) { + var promise, + test = this; + return function runHook() { + config.current = test; + if ( config.notrycatch ) { + promise = hook.call( test.testEnvironment, test.assert ); + test.resolvePromise( promise, hookName ); + return; } - this.testEnvironment.teardown.call( this.testEnvironment, this.assert ); - return; - } else { try { - this.testEnvironment.teardown.call( this.testEnvironment, this.assert ); - } catch ( e ) { - this.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 0 ) ); + promise = hook.call( test.testEnvironment, test.assert ); + test.resolvePromise( promise, hookName ); + } catch ( error ) { + test.pushFailure( hookName + " failed on " + test.testName + ": " + + ( error.message || error ), extractStacktrace( error, 0 ) ); } + }; + }, + + // Currently only used for module level hooks, can be used to add global level ones + hooks: function( handler ) { + var hooks = []; + + // Hooks are ignored on skipped tests + if ( this.skip ) { + return hooks; } - checkPollution(); + + if ( this.module.testEnvironment && + QUnit.objectType( this.module.testEnvironment[ handler ] ) === "function" ) { + hooks.push( this.queueHook( this.module.testEnvironment[ handler ], handler ) ); + } + + return hooks; }, + finish: function() { config.current = this; if ( config.requireExpects && this.expected === null ) { - this.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack ); + this.pushFailure( "Expected number of assertions to be defined, but expect() was " + + "not called.", this.stack ); } else if ( this.expected !== null && this.expected !== this.assertions.length ) { - this.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack ); + this.pushFailure( "Expected " + this.expected + " assertions, but " + + this.assertions.length + " were run", this.stack ); } else if ( this.expected === null && !this.assertions.length ) { - this.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack ); + this.pushFailure( "Expected at least one assertion, but none were run - call " + + "expect(0) to accept zero assertions.", this.stack ); } var i, @@ -847,7 +987,8 @@ Test.prototype = { runLoggingCallbacks( "testDone", { name: this.testName, - module: this.module, + module: this.module.name, + skipped: !!this.skip, failed: bad, passed: this.assertions.length - bad, total: this.assertions.length, @@ -855,12 +996,17 @@ Test.prototype = { // HTML Reporter use assertions: this.assertions, - testNumber: this.testNumber, + testId: this.testId, // DEPRECATED: this property will be removed in 2.0.0, use runtime instead duration: this.runtime }); + // QUnit.reset() is deprecated and will be replaced for a new + // fixture reset function on QUnit 2.0/2.1. + // It's still called here for backwards compatibility handling + QUnit.reset(); + config.current = undefined; }, @@ -868,26 +1014,39 @@ Test.prototype = { var bad, test = this; + if ( !this.valid() ) { + return; + } + function run() { + // each of these can by async - synchronize(function() { - test.setup(); - }); - synchronize(function() { - test.run(); - }); - synchronize(function() { - test.teardown(); - }); - synchronize(function() { - test.finish(); - }); + synchronize([ + function() { + test.before(); + }, + + test.hooks( "beforeEach" ), + + function() { + test.run(); + }, + + test.hooks( "afterEach" ).reverse(), + + function() { + test.after(); + }, + function() { + test.finish(); + } + ]); } // `bad` initialized at top of scope // defer when previous test run passed, if storage is available bad = QUnit.config.reorder && defined.sessionStorage && - +sessionStorage.getItem( "qunit-test-" + this.module + "-" + this.testName ); + +sessionStorage.getItem( "qunit-test-" + this.module.name + "-" + this.testName ); if ( bad ) { run(); @@ -899,13 +1058,14 @@ Test.prototype = { push: function( result, actual, expected, message ) { var source, details = { - module: this.module, + module: this.module.name, name: this.testName, result: result, message: message, actual: actual, expected: expected, - testNumber: this.testNumber + testId: this.testId, + runtime: now() - this.started }; if ( !result ) { @@ -926,16 +1086,18 @@ Test.prototype = { pushFailure: function( message, source, actual ) { if ( !this instanceof Test ) { - throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace( 2 ) ); + throw new Error( "pushFailure() assertion outside test context, was " + + sourceFromStacktrace( 2 ) ); } var details = { - module: this.module, + module: this.module.name, name: this.testName, result: false, message: message || "error", actual: actual || null, - testNumber: this.testNumber + testId: this.testId, + runtime: now() - this.started }; if ( source ) { @@ -948,20 +1110,132 @@ Test.prototype = { result: false, message: message }); + }, + + resolvePromise: function( promise, phase ) { + var then, message, + test = this; + if ( promise != null ) { + then = promise.then; + if ( QUnit.objectType( then ) === "function" ) { + QUnit.stop(); + then.call( + promise, + QUnit.start, + function( error ) { + message = "Promise rejected " + + ( !phase ? "during" : phase.replace( /Each$/, "" ) ) + + " " + test.testName + ": " + ( error.message || error ); + test.pushFailure( message, extractStacktrace( error, 0 ) ); + + // else next test will carry the responsibility + saveGlobal(); + + // Unblock + QUnit.start(); + } + ); + } + } + }, + + valid: function() { + var include, + filter = config.filter && config.filter.toLowerCase(), + module = QUnit.urlParams.module && QUnit.urlParams.module.toLowerCase(), + fullName = ( this.module.name + ": " + this.testName ).toLowerCase(); + + // Internally-generated tests are always valid + if ( this.callback && this.callback.validTest ) { + return true; + } + + if ( config.testId.length > 0 && inArray( this.testId, config.testId ) < 0 ) { + return false; + } + + if ( module && ( !this.module.name || this.module.name.toLowerCase() !== module ) ) { + return false; + } + + if ( !filter ) { + return true; + } + + include = filter.charAt( 0 ) !== "!"; + if ( !include ) { + filter = filter.slice( 1 ); + } + + // If the filter matches, we need to honour include + if ( fullName.indexOf( filter ) !== -1 ) { + return include; + } + + // Otherwise, do the opposite + return !include; + } + +}; + +// Resets the test setup. Useful for tests that modify the DOM. +/* +DEPRECATED: Use multiple tests instead of resetting inside a test. +Use testStart or testDone for custom cleanup. +This method will throw an error in 2.0, and will be removed in 2.1 +*/ +QUnit.reset = function() { + + // Return on non-browser environments + // This is necessary to not break on node tests + if ( typeof window === "undefined" ) { + return; + } + + var fixture = defined.document && document.getElementById && + document.getElementById( "qunit-fixture" ); + + if ( fixture ) { + fixture.innerHTML = config.fixture; } }; QUnit.pushFailure = function() { if ( !QUnit.config.current ) { - throw new Error( "pushFailure() assertion outside test context, in " + sourceFromStacktrace( 2 ) ); + throw new Error( "pushFailure() assertion outside test context, in " + + sourceFromStacktrace( 2 ) ); } // Gets current test obj - var currentTest = QUnit.config.current.assert.test; + var currentTest = QUnit.config.current; return currentTest.pushFailure.apply( currentTest, arguments ); }; +// Based on Java's String.hashCode, a simple but not +// rigorously collision resistant hashing function +function generateHash( module, testName ) { + var hex, + i = 0, + hash = 0, + str = module + "\x1C" + testName, + len = str.length; + + for ( ; i < len; i++ ) { + hash = ( ( hash << 5 ) - hash ) + str.charCodeAt( i ); + hash |= 0; + } + + // Convert the possibly negative integer hash code into an 8 character hex string, which isn't + // strictly necessary but increases user understanding that the id is a SHA-like hash + hex = ( 0x100000000 + hash ).toString( 16 ); + if ( hex.length < 8 ) { + hex = "0000000" + hex; + } + + return hex.slice( -8 ); +} + function Assert( testContext ) { this.test = testContext; } @@ -969,7 +1243,8 @@ function Assert( testContext ) { // Assert helpers QUnit.assert = Assert.prototype = { - // Specify the number of expected assertions to guarantee that failed test (no assertions are run at all) don't slip through. + // Specify the number of expected assertions to guarantee that failed test + // (no assertions are run at all) don't slip through. expect: function( asserts ) { if ( arguments.length === 1 ) { this.test.expected = asserts; @@ -978,20 +1253,51 @@ QUnit.assert = Assert.prototype = { } }, + // Increment this Test's semaphore counter, then return a single-use function that + // decrements that counter a maximum of once. + async: function() { + var test = this.test, + popped = false; + + test.semaphore += 1; + test.usedAsync = true; + pauseProcessing(); + + return function done() { + if ( !popped ) { + test.semaphore -= 1; + popped = true; + resumeProcessing(); + } else { + test.pushFailure( "Called the callback returned from `assert.async` more than once", + sourceFromStacktrace( 2 ) ); + } + }; + }, + // Exports test.push() to the user API - push: function() { - var assert = this; + push: function( /* result, actual, expected, message */ ) { + var assert = this, + currentTest = ( assert instanceof Assert && assert.test ) || QUnit.config.current; // Backwards compatibility fix. // Allows the direct use of global exported assertions and QUnit.assert.* // Although, it's use is not recommended as it can leak assertions // to other tests from async tests, because we only get a reference to the current test, // not exactly the test where assertion were intended to be called. - if ( !QUnit.config.current ) { + if ( !currentTest ) { throw new Error( "assertion outside test context, in " + sourceFromStacktrace( 2 ) ); } + + if ( currentTest.usedAsync === true && currentTest.semaphore === 0 ) { + currentTest.pushFailure( "Assertion after the final `assert.async` was resolved", + sourceFromStacktrace( 2 ) ); + + // Allow this assertion to continue running anyway... + } + if ( !( assert instanceof Assert ) ) { - assert = QUnit.config.current.assert; + assert = currentTest.assert; } return assert.test.push.apply( assert.test, arguments ); }, @@ -1005,11 +1311,7 @@ QUnit.assert = Assert.prototype = { ok: function( result, message ) { message = message || ( result ? "okay" : "failed, expected argument to be truthy, was: " + QUnit.dump.parse( result ) ); - if ( !!result ) { - this.push( true, result, true, message ); - } else { - this.test.pushFailure( message, null, result ); - } + this.push( !!result, result, true, message ); }, /** @@ -1017,7 +1319,7 @@ QUnit.assert = Assert.prototype = { * Prints out both actual and expected values. * @name equal * @function - * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" ); + * @example equal( format( "{0} bytes.", 2), "2 bytes.", "replaces {0} with next argument" ); */ equal: function( actual, expected, message ) { /*jshint eqeqeq:false */ @@ -1143,6 +1445,13 @@ QUnit.assert = Assert.prototype = { } }; +// Provide an alternative to assert.throws(), for enviroments that consider throws a reserved word +// Known to us are: Closure Compiler, Narwhal +(function() { + /*jshint sub:true */ + Assert.prototype.raises = Assert.prototype[ "throws" ]; +}()); + // Test for equality any JavaScript type. // Author: Philippe Rathé <prathe@gmail.com> QUnit.equiv = (function() { @@ -1356,7 +1665,8 @@ QUnit.equiv = (function() { } // apply transition with (1..n) arguments - }( args[ 0 ], args[ 1 ] ) ) && innerEquiv.apply( this, args.splice( 1, args.length - 1 ) ) ); + }( args[ 0 ], args[ 1 ] ) ) && + innerEquiv.apply( this, args.splice( 1, args.length - 1 ) ) ); }; return innerEquiv; @@ -1386,6 +1696,11 @@ QUnit.dump = (function() { function array( arr, stack ) { var i = arr.length, ret = new Array( i ); + + if ( dump.maxDepth && dump.depth > dump.maxDepth ) { + return "[object Array]"; + } + this.up(); while ( i-- ) { ret[ i ] = this.parse( arr[ i ], undefined, stack ); @@ -1396,25 +1711,28 @@ QUnit.dump = (function() { var reName = /^function (\w+)/, dump = { - // type is used mostly internally, you can fix a (custom)type in advance - parse: function( obj, type, stack ) { - stack = stack || []; - var inStack, res, - parser = this.parsers[ type || this.typeOf( obj ) ]; - type = typeof parser; - inStack = inArray( obj, stack ); + // objType is used mostly internally, you can fix a (custom) type in advance + parse: function( obj, objType, stack ) { + stack = stack || []; + var res, parser, parserType, + inStack = inArray( obj, stack ); if ( inStack !== -1 ) { return "recursion(" + ( inStack - stack.length ) + ")"; } - if ( type === "function" ) { + + objType = objType || this.typeOf( obj ); + parser = this.parsers[ objType ]; + parserType = typeof parser; + + if ( parserType === "function" ) { stack.push( obj ); res = parser.call( this, obj, stack ); stack.pop(); return res; } - return ( type === "string" ) ? parser : this.parsers.error; + return ( parserType === "string" ) ? parser : this.parsers.error; }, typeOf: function( obj ) { var type; @@ -1428,7 +1746,9 @@ QUnit.dump = (function() { type = "date"; } else if ( QUnit.is( "function", obj ) ) { type = "function"; - } else if ( typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined" ) { + } else if ( obj.setInterval !== undefined && + obj.document !== undefined && + obj.nodeType === undefined ) { type = "window"; } else if ( obj.nodeType === 9 ) { type = "document"; @@ -1440,7 +1760,9 @@ QUnit.dump = (function() { toString.call( obj ) === "[object Array]" || // NodeList objects - ( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item( 0 ) === obj[ 0 ] : ( obj.item( 0 ) === null && typeof obj[ 0 ] === "undefined" ) ) ) + ( typeof obj.length === "number" && obj.item !== undefined && + ( obj.length ? obj.item( 0 ) === obj[ 0 ] : ( obj.item( 0 ) === null && + obj[ 0 ] === undefined ) ) ) ) { type = "array"; } else if ( obj.constructor === Error.prototype.constructor ) { @@ -1451,7 +1773,7 @@ QUnit.dump = (function() { return type; }, separator: function() { - return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? " " : " "; + return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? " " : " "; }, // extra can be a number, shortcut for increasing-calling-decreasing indent: function( extra ) { @@ -1460,7 +1782,7 @@ QUnit.dump = (function() { } var chr = this.indentChar; if ( this.HTML ) { - chr = chr.replace( /\t/g, " " ).replace( / /g, " " ); + chr = chr.replace( /\t/g, " " ).replace( / /g, " " ); } return new Array( this.depth + ( extra || 0 ) ).join( chr ); }, @@ -1479,6 +1801,8 @@ QUnit.dump = (function() { join: join, // depth: 1, + maxDepth: 5, + // This is the list of parsers, to modify them, use dump.setParser parsers: { window: "[Window]", @@ -1491,6 +1815,7 @@ QUnit.dump = (function() { "undefined": "undefined", "function": function( fn ) { var ret = "function", + // functions never have name in IE name = "name" in fn ? fn.name : ( reName.exec( fn ) || [] )[ 1 ]; @@ -1506,8 +1831,13 @@ QUnit.dump = (function() { nodelist: array, "arguments": array, object: function( map, stack ) { - /*jshint forin:false */ - var ret = [], keys, key, val, i, nonEnumerableProperties; + var keys, key, val, i, nonEnumerableProperties, + ret = []; + + if ( dump.maxDepth && dump.depth > dump.maxDepth ) { + return "[object Object]"; + } + dump.up(); keys = []; for ( key in map ) { @@ -1526,7 +1856,8 @@ QUnit.dump = (function() { for ( i = 0; i < keys.length; i++ ) { key = keys[ i ]; val = map[ key ]; - ret.push( dump.parse( key, "key" ) + ": " + dump.parse( val, undefined, stack ) ); + ret.push( dump.parse( key, "key" ) + ": " + + dump.parse( val, undefined, stack ) ); } dump.down(); return join( "{", ret, "}" ); @@ -1543,10 +1874,12 @@ QUnit.dump = (function() { for ( i = 0, len = attrs.length; i < len; i++ ) { val = attrs[ i ].nodeValue; - // IE6 includes all attributes in .attributes, even ones not explicitly set. - // Those have values like undefined, null, 0, false, "" or "inherit". + // IE6 includes all attributes in .attributes, even ones not explicitly + // set. Those have values like undefined, null, 0, false, "" or + // "inherit". if ( val && val !== "inherit" ) { - ret += " " + attrs[ i ].nodeName + "=" + dump.parse( val, "attribute" ); + ret += " " + attrs[ i ].nodeName + "=" + + dump.parse( val, "attribute" ); } } } @@ -1653,17 +1986,23 @@ if ( typeof window !== "undefined" ) { window.QUnit = QUnit; } -// For CommonJS environments, export everything +// For nodejs if ( typeof module !== "undefined" && module.exports ) { module.exports = QUnit; } +// For CommonJS with exports, but without module.exports, like Rhino +if ( typeof exports !== "undefined" ) { + exports.QUnit = QUnit; +} + // Get a reference to the global object, like window in browsers }( (function() { return this; })() )); /*istanbul ignore next */ +// jscs:disable maximumLineLength /* * Javascript Diff Algorithm * By John Resig (http://ejohn.org/) @@ -1810,6 +2149,7 @@ QUnit.diff = (function() { return str; }; }()); +// jscs:enable (function() { @@ -1828,7 +2168,6 @@ QUnit.init = function() { config.autorun = false; config.filter = ""; config.queue = []; - config.semaphore = 1; // Return on non-browser environments // This is necessary to not break on node tests @@ -1867,27 +2206,7 @@ QUnit.init = function() { result.id = "qunit-testresult"; result.className = "result"; tests.parentNode.insertBefore( result, tests ); - result.innerHTML = "Running...<br/> "; - } -}; - -// Resets the test setup. Useful for tests that modify the DOM. -/* -DEPRECATED: Use multiple tests instead of resetting inside a test. -Use testStart or testDone for custom cleanup. -This method will throw an error in 2.0, and will be removed in 2.1 -*/ -QUnit.reset = function() { - - // Return on non-browser environments - // This is necessary to not break on node tests - if ( typeof window === "undefined" ) { - return; - } - - var fixture = id( "qunit-fixture" ); - if ( fixture ) { - fixture.innerHTML = config.fixture; + result.innerHTML = "Running...<br /> "; } }; @@ -1899,7 +2218,7 @@ if ( typeof window === "undefined" ) { var config = QUnit.config, hasOwn = Object.prototype.hasOwnProperty, defined = { - document: typeof window.document !== "undefined", + document: window.document !== undefined, sessionStorage: (function() { var x = "qunit-test-string"; try { @@ -1910,7 +2229,8 @@ var config = QUnit.config, return false; } }()) - }; + }, + modulesList = []; /** * Escape text for attribute or text content. @@ -2026,7 +2346,7 @@ function getUrlConfigHtml() { "' name='" + escaped + "' type='checkbox'" + ( val.value ? " value='" + escapeText( val.value ) + "'" : "" ) + ( config[ val.id ] ? " checked='checked'" : "" ) + - " title='" + escapedTooltip + "'><label for='qunit-urlconfig-" + escaped + + " title='" + escapedTooltip + "' /><label for='qunit-urlconfig-" + escaped + "' title='" + escapedTooltip + "'>" + val.label + "</label>"; } else { urlConfigHtml += "<label for='qunit-urlconfig-" + escaped + @@ -2064,6 +2384,38 @@ function getUrlConfigHtml() { return urlConfigHtml; } +// Handle "click" events on toolbar checkboxes and "change" for select menus. +// Updates the URL with the new state of `config.urlConfig` values. +function toolbarChanged() { + var updatedUrl, value, + field = this, + params = {}; + + // Detect if field is a select menu or a checkbox + if ( "selectedIndex" in field ) { + value = field.options[ field.selectedIndex ].value || undefined; + } else { + value = field.checked ? ( field.defaultValue || true ) : undefined; + } + + params[ field.name ] = value; + updatedUrl = QUnit.url( params ); + + if ( "hidepassed" === field.name && "replaceState" in window.history ) { + config[ field.name ] = value || false; + if ( value ) { + addClass( id( "qunit-tests" ), "hidepass" ); + } else { + removeClass( id( "qunit-tests" ), "hidepass" ); + } + + // It is not necessary to refresh the whole page + window.history.replaceState( null, "", updatedUrl ); + } else { + window.location = updatedUrl; + } +} + function toolbarUrlConfigContainer() { var urlConfigContainer = document.createElement( "span" ); @@ -2072,61 +2424,34 @@ function toolbarUrlConfigContainer() { // For oldIE support: // * Add handlers to the individual elements instead of the container // * Use "click" instead of "change" for checkboxes - // * Fallback from event.target to event.srcElement - addEvents( urlConfigContainer.getElementsByTagName( "input" ), "click", function( event ) { - var params = {}, - target = event.target || event.srcElement; - params[ target.name ] = target.checked ? - target.defaultValue || true : - undefined; - window.location = QUnit.url( params ); - }); - addEvents( urlConfigContainer.getElementsByTagName( "select" ), "change", function( event ) { - var params = {}, - target = event.target || event.srcElement; - params[ target.name ] = target.options[ target.selectedIndex ].value || undefined; - window.location = QUnit.url( params ); - }); + addEvents( urlConfigContainer.getElementsByTagName( "input" ), "click", toolbarChanged ); + addEvents( urlConfigContainer.getElementsByTagName( "select" ), "change", toolbarChanged ); return urlConfigContainer; } -function getModuleNames() { +function toolbarModuleFilterHtml() { var i, - moduleNames = []; + moduleFilterHtml = ""; - for ( i in config.modules ) { - if ( config.modules.hasOwnProperty( i ) ) { - moduleNames.push( i ); - } + if ( !modulesList.length ) { + return false; } - moduleNames.sort(function( a, b ) { + modulesList.sort(function( a, b ) { return a.localeCompare( b ); }); - return moduleNames; -} - -function toolbarModuleFilterHtml() { - var i, - moduleFilterHtml = "", - moduleNames = getModuleNames(); - - if ( moduleNames.length <= 1 ) { - return false; - } - moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label>" + "<select id='qunit-modulefilter' name='modulefilter'><option value='' " + - ( config.module === undefined ? "selected='selected'" : "" ) + + ( QUnit.urlParams.module === undefined ? "selected='selected'" : "" ) + ">< All Modules ></option>"; - for ( i = 0; i < moduleNames.length; i++ ) { + for ( i = 0; i < modulesList.length; i++ ) { moduleFilterHtml += "<option value='" + - escapeText( encodeURIComponent( moduleNames[ i ] ) ) + "' " + - ( config.module === moduleNames[ i ] ? "selected='selected'" : "" ) + - ">" + escapeText( moduleNames[ i ] ) + "</option>"; + escapeText( encodeURIComponent( modulesList[ i ] ) ) + "' " + + ( QUnit.urlParams.module === modulesList[ i ] ? "selected='selected'" : "" ) + + ">" + escapeText( modulesList[ i ] ) + "</option>"; } moduleFilterHtml += "</select>"; @@ -2134,7 +2459,8 @@ function toolbarModuleFilterHtml() { } function toolbarModuleFilter() { - var moduleFilter = document.createElement( "span" ), + var toolbar = id( "qunit-testrunner-toolbar" ), + moduleFilter = document.createElement( "span" ), moduleFilterHtml = toolbarModuleFilterHtml(); if ( !moduleFilterHtml ) { @@ -2146,73 +2472,25 @@ function toolbarModuleFilter() { addEvent( moduleFilter.lastChild, "change", function() { var selectBox = moduleFilter.getElementsByTagName( "select" )[ 0 ], - selectedModule = decodeURIComponent( selectBox.options[ selectBox.selectedIndex ].value ); + selection = decodeURIComponent( selectBox.options[ selectBox.selectedIndex ].value ); window.location = QUnit.url({ - module: ( selectedModule === "" ) ? undefined : selectedModule, + module: ( selection === "" ) ? undefined : selection, // Remove any existing filters filter: undefined, - testNumber: undefined + testId: undefined }); }); - return moduleFilter; -} - -function toolbarFilter() { - var testList = id( "qunit-tests" ), - filter = document.createElement( "input" ); - - filter.type = "checkbox"; - filter.id = "qunit-filter-pass"; - - addEvent( filter, "click", function() { - if ( filter.checked ) { - addClass( testList, "hidepass" ); - if ( defined.sessionStorage ) { - sessionStorage.setItem( "qunit-filter-passed-tests", "true" ); - } - } else { - removeClass( testList, "hidepass" ); - if ( defined.sessionStorage ) { - sessionStorage.removeItem( "qunit-filter-passed-tests" ); - } - } - }); - - if ( config.hidepassed || defined.sessionStorage && - sessionStorage.getItem( "qunit-filter-passed-tests" ) ) { - filter.checked = true; - - addClass( testList, "hidepass" ); - } - - return filter; -} - -function toolbarLabel() { - var label = document.createElement( "label" ); - label.setAttribute( "for", "qunit-filter-pass" ); - label.setAttribute( "title", "Only show tests and assertions that fail. Stored in sessionStorage." ); - label.innerHTML = "Hide passed tests"; - - return label; + toolbar.appendChild( moduleFilter ); } function appendToolbar() { - var moduleFilter, - toolbar = id( "qunit-testrunner-toolbar" ); + var toolbar = id( "qunit-testrunner-toolbar" ); if ( toolbar ) { - toolbar.appendChild( toolbarFilter() ); - toolbar.appendChild( toolbarLabel() ); toolbar.appendChild( toolbarUrlConfigContainer() ); - - moduleFilter = toolbarModuleFilter(); - if ( moduleFilter ) { - toolbar.appendChild( moduleFilter ); - } } } @@ -2222,7 +2500,7 @@ function appendBanner() { if ( banner ) { banner.className = ""; banner.innerHTML = "<a href='" + - QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + + QUnit.url({ filter: undefined, module: undefined, testId: undefined }) + "'>" + banner.innerHTML + "</a> "; } } @@ -2241,7 +2519,7 @@ function appendTestResults() { result.id = "qunit-testresult"; result.className = "result"; tests.parentNode.insertBefore( result, tests ); - result.innerHTML = "Running...<br> "; + result.innerHTML = "Running...<br /> "; } } @@ -2259,24 +2537,80 @@ function appendUserAgent() { } } +function appendTestsList( modules ) { + var i, l, x, z, test, moduleObj; + + for ( i = 0, l = modules.length; i < l; i++ ) { + moduleObj = modules[ i ]; + + if ( moduleObj.name ) { + modulesList.push( moduleObj.name ); + } + + for ( x = 0, z = moduleObj.tests.length; x < z; x++ ) { + test = moduleObj.tests[ x ]; + + appendTest( test.name, test.testId, moduleObj.name ); + } + } +} + +function appendTest( name, testId, moduleName ) { + var title, rerunTrigger, testBlock, assertList, + tests = id( "qunit-tests" ); + + if ( !tests ) { + return; + } + + title = document.createElement( "strong" ); + title.innerHTML = getNameHtml( name, moduleName ); + + rerunTrigger = document.createElement( "a" ); + rerunTrigger.innerHTML = "Rerun"; + rerunTrigger.href = QUnit.url({ testId: testId }); + + testBlock = document.createElement( "li" ); + testBlock.appendChild( title ); + testBlock.appendChild( rerunTrigger ); + testBlock.id = "qunit-test-output-" + testId; + + assertList = document.createElement( "ol" ); + assertList.className = "qunit-assert-list"; + + testBlock.appendChild( assertList ); + + tests.appendChild( testBlock ); +} + // HTML Reporter initialization and load -QUnit.begin(function() { +QUnit.begin(function( details ) { var qunit = id( "qunit" ); - if ( qunit ) { - qunit.innerHTML = + // Fixture is the only one necessary to run without the #qunit element + storeFixture(); + + if ( !qunit ) { + return; + } + + qunit.innerHTML = "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" + "<h2 id='qunit-banner'></h2>" + "<div id='qunit-testrunner-toolbar'></div>" + "<h2 id='qunit-userAgent'></h2>" + "<ol id='qunit-tests'></ol>"; - } appendBanner(); appendTestResults(); appendUserAgent(); appendToolbar(); - storeFixture(); + appendTestsList( details.modules ); + toolbarModuleFilter(); + + if ( config.hidepassed ) { + addClass( qunit.lastChild, "hidepass" ); + } }); QUnit.done(function( details ) { @@ -2286,7 +2620,7 @@ QUnit.done(function( details ) { html = [ "Tests completed in ", details.runtime, - " milliseconds.<br>", + " milliseconds.<br />", "<span class='passed'>", details.passed, "</span> assertions of <span class='total'>", @@ -2343,35 +2677,20 @@ function getNameHtml( name, module ) { } QUnit.testStart(function( details ) { - var a, b, li, running, assertList, - name = getNameHtml( details.name, details.module ), - tests = id( "qunit-tests" ); - - if ( tests ) { - b = document.createElement( "strong" ); - b.innerHTML = name; + var running, testBlock; - a = document.createElement( "a" ); - a.innerHTML = "Rerun"; - a.href = QUnit.url({ testNumber: details.testNumber }); - - li = document.createElement( "li" ); - li.appendChild( b ); - li.appendChild( a ); - li.className = "running"; - li.id = "qunit-test-output" + details.testNumber; - - assertList = document.createElement( "ol" ); - assertList.className = "qunit-assert-list"; - - li.appendChild( assertList ); + testBlock = id( "qunit-test-output-" + details.testId ); + if ( testBlock ) { + testBlock.className = "running"; + } else { - tests.appendChild( li ); + // Report later registered tests + appendTest( details.name, details.testId, details.module ); } running = id( "qunit-testresult" ); if ( running ) { - running.innerHTML = "Running: <br>" + name; + running.innerHTML = "Running: <br />" + getNameHtml( details.name, details.module ); } }); @@ -2379,7 +2698,7 @@ QUnit.testStart(function( details ) { QUnit.log(function( details ) { var assertList, assertLi, message, expected, actual, - testItem = id( "qunit-test-output" + details.testNumber ); + testItem = id( "qunit-test-output-" + details.testId ); if ( !testItem ) { return; @@ -2387,6 +2706,7 @@ QUnit.log(function( details ) { message = escapeText( details.message ) || ( details.result ? "okay" : "failed" ); message = "<span class='test-message'>" + message + "</span>"; + message += "<span class='runtime'>@ " + details.runtime + " ms</span>"; // pushFailure doesn't provide details.expected // when it calls, it's implicit to also not show expected and diff stuff @@ -2430,19 +2750,15 @@ QUnit.log(function( details ) { QUnit.testDone(function( details ) { var testTitle, time, testItem, assertList, - good, bad, testCounts, + good, bad, testCounts, skipped, tests = id( "qunit-tests" ); - // QUnit.reset() is deprecated and will be replaced for a new - // fixture reset function on QUnit 2.0/2.1. - // It's still called here for backwards compatibility handling - QUnit.reset(); - if ( !tests ) { return; } - testItem = id( "qunit-test-output" + details.testNumber ); + testItem = id( "qunit-test-output-" + details.testId ); + assertList = testItem.getElementsByTagName( "ol" )[ 0 ]; good = details.passed; @@ -2471,20 +2787,28 @@ QUnit.testDone(function( details ) { testTitle.innerHTML += " <b class='counts'>(" + testCounts + details.assertions.length + ")</b>"; - addEvent( testTitle, "click", function() { - toggleClass( assertList, "qunit-collapsed" ); - }); - - time = document.createElement( "span" ); - time.className = "runtime"; - time.innerHTML = details.runtime + " ms"; + if ( details.skipped ) { + addClass( testItem, "skipped" ); + skipped = document.createElement( "em" ); + skipped.className = "qunit-skipped-label"; + skipped.innerHTML = "skipped"; + testItem.insertBefore( skipped, testTitle ); + } else { + addEvent( testTitle, "click", function() { + toggleClass( assertList, "qunit-collapsed" ); + }); - testItem.className = bad ? "fail" : "pass"; + testItem.className = bad ? "fail" : "pass"; - testItem.insertBefore( time, assertList ); + time = document.createElement( "span" ); + time.className = "runtime"; + time.innerHTML = details.runtime + " ms"; + testItem.insertBefore( time, assertList ); + } }); if ( !defined.document || document.readyState === "complete" ) { + config.pageLoaded = true; config.autorun = true; } diff --git a/web/src/vendor/react-bootstrap/react-bootstrap.js b/web/src/vendor/react-bootstrap/react-bootstrap.js deleted file mode 100644 index b803cae8..00000000 --- a/web/src/vendor/react-bootstrap/react-bootstrap.js +++ /dev/null @@ -1,5346 +0,0 @@ -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - // AMD. - define(['react'], factory); - } else { - // Browser globals - root.ReactBootstrap = factory(root.React); - } -}(this, function (React) { - -/** - * almond 0.1.2 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/almond for details - */ -//Going sloppy to avoid 'use strict' string cost, but strict practices should -//be followed. -/*jslint sloppy: true */ -/*global setTimeout: false */ - -var requirejs, require, define; -(function (undef) { - var defined = {}, - waiting = {}, - config = {}, - defining = {}, - aps = [].slice, - main, req; - - /** - * Given a relative module name, like ./something, normalize it to - * a real name that can be mapped to a path. - * @param {String} name the relative name - * @param {String} baseName a real name that the name arg is relative - * to. - * @returns {String} normalized name - */ - function normalize(name, baseName) { - var baseParts = baseName && baseName.split("/"), - map = config.map, - starMap = (map && map['*']) || {}, - nameParts, nameSegment, mapValue, foundMap, - foundI, foundStarMap, starI, i, j, part; - - //Adjust any relative paths. - if (name && name.charAt(0) === ".") { - //If have a base name, try to normalize against it, - //otherwise, assume it is a top-level require that will - //be relative to baseUrl in the end. - if (baseName) { - //Convert baseName to array, and lop off the last part, - //so that . matches that "directory" and not name of the baseName's - //module. For instance, baseName of "one/two/three", maps to - //"one/two/three.js", but we want the directory, "one/two" for - //this normalization. - baseParts = baseParts.slice(0, baseParts.length - 1); - - name = baseParts.concat(name.split("/")); - - //start trimDots - for (i = 0; (part = name[i]); i++) { - if (part === ".") { - name.splice(i, 1); - i -= 1; - } else if (part === "..") { - if (i === 1 && (name[2] === '..' || name[0] === '..')) { - //End of the line. Keep at least one non-dot - //path segment at the front so it can be mapped - //correctly to disk. Otherwise, there is likely - //no path mapping for a path starting with '..'. - //This can still fail, but catches the most reasonable - //uses of .. - return true; - } else if (i > 0) { - name.splice(i - 1, 2); - i -= 2; - } - } - } - //end trimDots - - name = name.join("/"); - } - } - - //Apply map config if available. - if ((baseParts || starMap) && map) { - nameParts = name.split('/'); - - for (i = nameParts.length; i > 0; i -= 1) { - nameSegment = nameParts.slice(0, i).join("/"); - - if (baseParts) { - //Find the longest baseName segment match in the config. - //So, do joins on the biggest to smallest lengths of baseParts. - for (j = baseParts.length; j > 0; j -= 1) { - mapValue = map[baseParts.slice(0, j).join('/')]; - - //baseName segment has config, find if it has one for - //this name. - if (mapValue) { - mapValue = mapValue[nameSegment]; - if (mapValue) { - //Match, update name to the new value. - foundMap = mapValue; - foundI = i; - break; - } - } - } - } - - if (foundMap) { - break; - } - - //Check for a star map match, but just hold on to it, - //if there is a shorter segment match later in a matching - //config, then favor over this star map. - if (!foundStarMap && starMap && starMap[nameSegment]) { - foundStarMap = starMap[nameSegment]; - starI = i; - } - } - - if (!foundMap && foundStarMap) { - foundMap = foundStarMap; - foundI = starI; - } - - if (foundMap) { - nameParts.splice(0, foundI, foundMap); - name = nameParts.join('/'); - } - } - - return name; - } - - function makeRequire(relName, forceSync) { - return function () { - //A version of a require function that passes a moduleName - //value for items that may need to - //look up paths relative to the moduleName - return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync])); - }; - } - - function makeNormalize(relName) { - return function (name) { - return normalize(name, relName); - }; - } - - function makeLoad(depName) { - return function (value) { - defined[depName] = value; - }; - } - - function callDep(name) { - if (waiting.hasOwnProperty(name)) { - var args = waiting[name]; - delete waiting[name]; - defining[name] = true; - main.apply(undef, args); - } - - if (!defined.hasOwnProperty(name)) { - throw new Error('No ' + name); - } - return defined[name]; - } - - /** - * Makes a name map, normalizing the name, and using a plugin - * for normalization if necessary. Grabs a ref to plugin - * too, as an optimization. - */ - function makeMap(name, relName) { - var prefix, plugin, - index = name.indexOf('!'); - - if (index !== -1) { - prefix = normalize(name.slice(0, index), relName); - name = name.slice(index + 1); - plugin = callDep(prefix); - - //Normalize according - if (plugin && plugin.normalize) { - name = plugin.normalize(name, makeNormalize(relName)); - } else { - name = normalize(name, relName); - } - } else { - name = normalize(name, relName); - } - - //Using ridiculous property names for space reasons - return { - f: prefix ? prefix + '!' + name : name, //fullName - n: name, - p: plugin - }; - } - - function makeConfig(name) { - return function () { - return (config && config.config && config.config[name]) || {}; - }; - } - - main = function (name, deps, callback, relName) { - var args = [], - usingExports, - cjsModule, depName, ret, map, i; - - //Use name if no relName - relName = relName || name; - - //Call the callback to define the module, if necessary. - if (typeof callback === 'function') { - - //Pull out the defined dependencies and pass the ordered - //values to the callback. - //Default to [require, exports, module] if no deps - deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; - for (i = 0; i < deps.length; i++) { - map = makeMap(deps[i], relName); - depName = map.f; - - //Fast path CommonJS standard dependencies. - if (depName === "require") { - args[i] = makeRequire(name); - } else if (depName === "exports") { - //CommonJS module spec 1.1 - args[i] = defined[name] = {}; - usingExports = true; - } else if (depName === "module") { - //CommonJS module spec 1.1 - cjsModule = args[i] = { - id: name, - uri: '', - exports: defined[name], - config: makeConfig(name) - }; - } else if (defined.hasOwnProperty(depName) || waiting.hasOwnProperty(depName)) { - args[i] = callDep(depName); - } else if (map.p) { - map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); - args[i] = defined[depName]; - } else if (!defining[depName]) { - throw new Error(name + ' missing ' + depName); - } - } - - ret = callback.apply(defined[name], args); - - if (name) { - //If setting exports via "module" is in play, - //favor that over return value and exports. After that, - //favor a non-undefined return value over exports use. - if (cjsModule && cjsModule.exports !== undef && - cjsModule.exports !== defined[name]) { - defined[name] = cjsModule.exports; - } else if (ret !== undef || !usingExports) { - //Use the return value from the function. - defined[name] = ret; - } - } - } else if (name) { - //May just be an object definition for the module. Only - //worry about defining if have a module name. - defined[name] = callback; - } - }; - - requirejs = require = req = function (deps, callback, relName, forceSync) { - if (typeof deps === "string") { - //Just return the module wanted. In this scenario, the - //deps arg is the module name, and second arg (if passed) - //is just the relName. - //Normalize module name, if it contains . or .. - return callDep(makeMap(deps, callback).f); - } else if (!deps.splice) { - //deps is a config object, not an array. - config = deps; - if (callback.splice) { - //callback is an array, which means it is a dependency list. - //Adjust args if there are dependencies - deps = callback; - callback = relName; - relName = null; - } else { - deps = undef; - } - } - - //Support require(['a']) - callback = callback || function () {}; - - //Simulate async callback; - if (forceSync) { - main(undef, deps, callback, relName); - } else { - setTimeout(function () { - main(undef, deps, callback, relName); - }, 15); - } - - return req; - }; - - /** - * Just drops the config on the floor, but returns req in case - * the config return value is used. - */ - req.config = function (cfg) { - config = cfg; - return req; - }; - - define = function (name, deps, callback) { - - //This module may not have dependencies - if (!deps.splice) { - //deps is not an array, so probably means - //an object literal or factory function for - //the value. Adjust args. - callback = deps; - deps = []; - } - - waiting[name] = [name, deps, callback]; - }; - - define.amd = { - jQuery: true - }; -}()); - -define("almond", function(){}); - -define('utils/classSet',['require','exports','module'],function (require, exports, module) {/** - * React classSet - * - * Copyright 2013-2014 Facebook, Inc. - * @licence https://github.com/facebook/react/blob/0.11-stable/LICENSE - * - * This file is unmodified from: - * https://github.com/facebook/react/blob/0.11-stable/src/vendor/stubs/cx.js - * - */ - -/** - * This function is used to mark string literals representing CSS class names - * so that they can be transformed statically. This allows for modularization - * and minification of CSS class names. - * - * In static_upstream, this function is actually implemented, but it should - * eventually be replaced with something more descriptive, and the transform - * that is used in the main stack should be ported for use elsewhere. - * - * @param string|object className to modularize, or an object of key/values. - * In the object case, the values are conditions that - * determine if the className keys should be included. - * @param [string ...] Variable list of classNames in the string case. - * @return string Renderable space-separated CSS className. - */ -function cx(classNames) { - if (typeof classNames == 'object') { - return Object.keys(classNames).filter(function(className) { - return classNames[className]; - }).join(' '); - } else { - return Array.prototype.join.call(arguments, ' '); - } -} - -module.exports = cx; -}); - -define('utils/merge',['require','exports','module'],function (require, exports, module) {/** - * Merge helper - * - * TODO: to be replaced with ES6's `Object.assign()` for React 0.12 - */ - -/** - * Shallow merges two structures by mutating the first parameter. - * - * @param {object} one Object to be merged into. - * @param {?object} two Optional object with properties to merge from. - */ -function mergeInto(one, two) { - if (two != null) { - for (var key in two) { - if (!two.hasOwnProperty(key)) { - continue; - } - one[key] = two[key]; - } - } -} - -/** - * Shallow merges two structures into a return value, without mutating either. - * - * @param {?object} one Optional object with properties to merge from. - * @param {?object} two Optional object with properties to merge from. - * @return {object} The shallow extension of one by two. - */ -function merge(one, two) { - var result = {}; - mergeInto(result, one); - mergeInto(result, two); - return result; -} - -module.exports = merge; -}); - -define('utils/cloneWithProps',['require','exports','module','react','./merge'],function (require, exports, module) {/** - * React cloneWithProps - * - * Copyright 2013-2014 Facebook, Inc. - * @licence https://github.com/facebook/react/blob/0.11-stable/LICENSE - * - * This file contains modified versions of: - * https://github.com/facebook/react/blob/0.11-stable/src/utils/cloneWithProps.js - * https://github.com/facebook/react/blob/0.11-stable/src/core/ReactPropTransferer.js - * https://github.com/facebook/react/blob/0.11-stable/src/utils/joinClasses.js - * - * TODO: This should be replaced as soon as cloneWithProps is available via - * the core React package or a separate package. - * @see https://github.com/facebook/react/issues/1906 - * - */ - -var React = require('react'); -var merge = require('./merge'); - -/** - * Combines multiple className strings into one. - * http://jsperf.com/joinclasses-args-vs-array - * - * @param {...?string} classes - * @return {string} - */ -function joinClasses(className/*, ... */) { - if (!className) { - className = ''; - } - var nextClass; - var argLength = arguments.length; - if (argLength > 1) { - for (var ii = 1; ii < argLength; ii++) { - nextClass = arguments[ii]; - nextClass && (className += ' ' + nextClass); - } - } - return className; -} - -/** - * Creates a transfer strategy that will merge prop values using the supplied - * `mergeStrategy`. If a prop was previously unset, this just sets it. - * - * @param {function} mergeStrategy - * @return {function} - */ -function createTransferStrategy(mergeStrategy) { - return function(props, key, value) { - if (!props.hasOwnProperty(key)) { - props[key] = value; - } else { - props[key] = mergeStrategy(props[key], value); - } - }; -} - -var transferStrategyMerge = createTransferStrategy(function(a, b) { - // `merge` overrides the first object's (`props[key]` above) keys using the - // second object's (`value`) keys. An object's style's existing `propA` would - // get overridden. Flip the order here. - return merge(b, a); -}); - -function emptyFunction() {} - -/** - * Transfer strategies dictate how props are transferred by `transferPropsTo`. - * NOTE: if you add any more exceptions to this list you should be sure to - * update `cloneWithProps()` accordingly. - */ -var TransferStrategies = { - /** - * Never transfer `children`. - */ - children: emptyFunction, - /** - * Transfer the `className` prop by merging them. - */ - className: createTransferStrategy(joinClasses), - /** - * Never transfer the `key` prop. - */ - key: emptyFunction, - /** - * Never transfer the `ref` prop. - */ - ref: emptyFunction, - /** - * Transfer the `style` prop (which is an object) by merging them. - */ - style: transferStrategyMerge -}; - -/** - * Mutates the first argument by transferring the properties from the second - * argument. - * - * @param {object} props - * @param {object} newProps - * @return {object} - */ -function transferInto(props, newProps) { - for (var thisKey in newProps) { - if (!newProps.hasOwnProperty(thisKey)) { - continue; - } - - var transferStrategy = TransferStrategies[thisKey]; - - if (transferStrategy && TransferStrategies.hasOwnProperty(thisKey)) { - transferStrategy(props, thisKey, newProps[thisKey]); - } else if (!props.hasOwnProperty(thisKey)) { - props[thisKey] = newProps[thisKey]; - } - } - return props; -} - -/** - * Merge two props objects using TransferStrategies. - * - * @param {object} oldProps original props (they take precedence) - * @param {object} newProps new props to merge in - * @return {object} a new object containing both sets of props merged. - */ -function mergeProps(oldProps, newProps) { - return transferInto(merge(oldProps), newProps); -} - -var ReactPropTransferer = { - mergeProps: mergeProps -}; - -var CHILDREN_PROP = 'children'; - -/** - * Sometimes you want to change the props of a child passed to you. Usually - * this is to add a CSS class. - * - * @param {object} child child component you'd like to clone - * @param {object} props props you'd like to modify. They will be merged - * as if you used `transferPropsTo()`. - * @return {object} a clone of child with props merged in. - */ -function cloneWithProps(child, props) { - var newProps = ReactPropTransferer.mergeProps(props, child.props); - - // Use `child.props.children` if it is provided. - if (!newProps.hasOwnProperty(CHILDREN_PROP) && - child.props.hasOwnProperty(CHILDREN_PROP)) { - newProps.children = child.props.children; - } - - // Huge hack to support both the 0.10 API and the new way of doing things - // TODO: remove when support for 0.10 is no longer needed - if (React.version.indexOf('0.10.') === 0) { - return child.constructor.ConvenienceConstructor(newProps); - } - - - // The current API doesn't retain _owner and _context, which is why this - // doesn't use ReactDescriptor.cloneAndReplaceProps. - return child.constructor(newProps); -} - -module.exports = cloneWithProps; -}); - -define('constants',['require','exports','module'],function (require, exports, module) {module.exports = { - CLASSES: { - 'alert': 'alert', - 'button': 'btn', - 'button-group': 'btn-group', - 'button-toolbar': 'btn-toolbar', - 'column': 'col', - 'input-group': 'input-group', - 'form': 'form', - 'glyphicon': 'glyphicon', - 'label': 'label', - 'list-group-item': 'list-group-item', - 'panel': 'panel', - 'panel-group': 'panel-group', - 'progress-bar': 'progress-bar', - 'nav': 'nav', - 'navbar': 'navbar', - 'modal': 'modal', - 'row': 'row', - 'well': 'well' - }, - STYLES: { - 'default': 'default', - 'primary': 'primary', - 'success': 'success', - 'info': 'info', - 'warning': 'warning', - 'danger': 'danger', - 'link': 'link', - 'inline': 'inline', - 'tabs': 'tabs', - 'pills': 'pills' - }, - SIZES: { - 'large': 'lg', - 'medium': 'md', - 'small': 'sm', - 'xsmall': 'xs' - }, - GLYPHS: [ - 'asterisk', - 'plus', - 'euro', - 'minus', - 'cloud', - 'envelope', - 'pencil', - 'glass', - 'music', - 'search', - 'heart', - 'star', - 'star-empty', - 'user', - 'film', - 'th-large', - 'th', - 'th-list', - 'ok', - 'remove', - 'zoom-in', - 'zoom-out', - 'off', - 'signal', - 'cog', - 'trash', - 'home', - 'file', - 'time', - 'road', - 'download-alt', - 'download', - 'upload', - 'inbox', - 'play-circle', - 'repeat', - 'refresh', - 'list-alt', - 'lock', - 'flag', - 'headphones', - 'volume-off', - 'volume-down', - 'volume-up', - 'qrcode', - 'barcode', - 'tag', - 'tags', - 'book', - 'bookmark', - 'print', - 'camera', - 'font', - 'bold', - 'italic', - 'text-height', - 'text-width', - 'align-left', - 'align-center', - 'align-right', - 'align-justify', - 'list', - 'indent-left', - 'indent-right', - 'facetime-video', - 'picture', - 'map-marker', - 'adjust', - 'tint', - 'edit', - 'share', - 'check', - 'move', - 'step-backward', - 'fast-backward', - 'backward', - 'play', - 'pause', - 'stop', - 'forward', - 'fast-forward', - 'step-forward', - 'eject', - 'chevron-left', - 'chevron-right', - 'plus-sign', - 'minus-sign', - 'remove-sign', - 'ok-sign', - 'question-sign', - 'info-sign', - 'screenshot', - 'remove-circle', - 'ok-circle', - 'ban-circle', - 'arrow-left', - 'arrow-right', - 'arrow-up', - 'arrow-down', - 'share-alt', - 'resize-full', - 'resize-small', - 'exclamation-sign', - 'gift', - 'leaf', - 'fire', - 'eye-open', - 'eye-close', - 'warning-sign', - 'plane', - 'calendar', - 'random', - 'comment', - 'magnet', - 'chevron-up', - 'chevron-down', - 'retweet', - 'shopping-cart', - 'folder-close', - 'folder-open', - 'resize-vertical', - 'resize-horizontal', - 'hdd', - 'bullhorn', - 'bell', - 'certificate', - 'thumbs-up', - 'thumbs-down', - 'hand-right', - 'hand-left', - 'hand-up', - 'hand-down', - 'circle-arrow-right', - 'circle-arrow-left', - 'circle-arrow-up', - 'circle-arrow-down', - 'globe', - 'wrench', - 'tasks', - 'filter', - 'briefcase', - 'fullscreen', - 'dashboard', - 'paperclip', - 'heart-empty', - 'link', - 'phone', - 'pushpin', - 'usd', - 'gbp', - 'sort', - 'sort-by-alphabet', - 'sort-by-alphabet-alt', - 'sort-by-order', - 'sort-by-order-alt', - 'sort-by-attributes', - 'sort-by-attributes-alt', - 'unchecked', - 'expand', - 'collapse-down', - 'collapse-up', - 'log-in', - 'flash', - 'log-out', - 'new-window', - 'record', - 'save', - 'open', - 'saved', - 'import', - 'export', - 'send', - 'floppy-disk', - 'floppy-saved', - 'floppy-remove', - 'floppy-save', - 'floppy-open', - 'credit-card', - 'transfer', - 'cutlery', - 'header', - 'compressed', - 'earphone', - 'phone-alt', - 'tower', - 'stats', - 'sd-video', - 'hd-video', - 'subtitles', - 'sound-stereo', - 'sound-dolby', - 'sound-5-1', - 'sound-6-1', - 'sound-7-1', - 'copyright-mark', - 'registration-mark', - 'cloud-download', - 'cloud-upload', - 'tree-conifer', - 'tree-deciduous' - ] -}; - -}); - -define('BootstrapMixin',['require','exports','module','react','./constants'],function (require, exports, module) {var React = require('react'); -var constants = require('./constants'); - -var BootstrapMixin = { - propTypes: { - bsClass: React.PropTypes.oneOf(Object.keys(constants.CLASSES)), - bsStyle: React.PropTypes.oneOf(Object.keys(constants.STYLES)), - bsSize: React.PropTypes.oneOf(Object.keys(constants.SIZES)) - }, - - getBsClassSet: function () { - var classes = {}; - - var bsClass = this.props.bsClass && constants.CLASSES[this.props.bsClass]; - if (bsClass) { - classes[bsClass] = true; - - var prefix = bsClass + '-'; - - var bsSize = this.props.bsSize && constants.SIZES[this.props.bsSize]; - if (bsSize) { - classes[prefix + bsSize] = true; - } - - var bsStyle = this.props.bsStyle && constants.STYLES[this.props.bsStyle]; - if (this.props.bsStyle) { - classes[prefix + bsStyle] = true; - } - } - - return classes; - } -}; - -module.exports = BootstrapMixin; -}); - -define('utils/ValidComponentChildren',['require','exports','module','react'],function (require, exports, module) {var React = require('react'); - -/** - * Maps children that are typically specified as `props.children`, - * but only iterates over children that are "valid components". - * - * The mapFunction provided index will be normalised to the components mapped, - * so an invalid component would not increase the index. - * - * @param {?*} children Children tree container. - * @param {function(*, int)} mapFunction. - * @param {*} mapContext Context for mapFunction. - * @return {object} Object containing the ordered map of results. - */ -function mapValidComponents(children, func, context) { - var index = 0; - - return React.Children.map(children, function (child) { - if (React.isValidComponent(child)) { - var lastIndex = index; - index++; - return func.call(context, child, lastIndex); - } - - return child; - }); -} - -/** - * Iterates through children that are typically specified as `props.children`, - * but only iterates over children that are "valid components". - * - * The provided forEachFunc(child, index) will be called for each - * leaf child with the index reflecting the position relative to "valid components". - * - * @param {?*} children Children tree container. - * @param {function(*, int)} forEachFunc. - * @param {*} forEachContext Context for forEachContext. - */ -function forEachValidComponents(children, func, context) { - var index = 0; - - return React.Children.forEach(children, function (child) { - if (React.isValidComponent(child)) { - func.call(context, child, index); - index++; - } - }); -} - -/** - * Count the number of "valid components" in the Children container. - * - * @param {?*} children Children tree container. - * @returns {number} - */ -function numberOfValidComponents(children) { - var count = 0; - - React.Children.forEach(children, function (child) { - if (React.isValidComponent(child)) { count++; } - }); - - return count; -} - -/** - * Determine if the Child container has one or more "valid components". - * - * @param {?*} children Children tree container. - * @returns {boolean} - */ -function hasValidComponent(children) { - var hasValid = false; - - React.Children.forEach(children, function (child) { - if (!hasValid && React.isValidComponent(child)) { - hasValid = true; - } - }); - - return hasValid; -} - -module.exports = { - map: mapValidComponents, - forEach: forEachValidComponents, - numberOf: numberOfValidComponents, - hasValidComponent: hasValidComponent -}; -}); - -define('PanelGroup',['require','exports','module','react','./utils/classSet','./utils/cloneWithProps','./BootstrapMixin','./utils/ValidComponentChildren'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var cloneWithProps = require('./utils/cloneWithProps'); -var BootstrapMixin = require('./BootstrapMixin'); -var ValidComponentChildren = require('./utils/ValidComponentChildren'); - -var PanelGroup = React.createClass({displayName: 'PanelGroup', - mixins: [BootstrapMixin], - - propTypes: { - collapsable: React.PropTypes.bool, - activeKey: React.PropTypes.any, - defaultActiveKey: React.PropTypes.any, - onSelect: React.PropTypes.func - }, - - getDefaultProps: function () { - return { - bsClass: 'panel-group' - }; - }, - - getInitialState: function () { - var defaultActiveKey = this.props.defaultActiveKey; - - return { - activeKey: defaultActiveKey - }; - }, - - render: function () { - return this.transferPropsTo( - React.DOM.div( {className:classSet(this.getBsClassSet()), onSelect:null}, - ValidComponentChildren.map(this.props.children, this.renderPanel) - ) - ); - }, - - renderPanel: function (child) { - var activeKey = - this.props.activeKey != null ? this.props.activeKey : this.state.activeKey; - - var props = { - bsStyle: child.props.bsStyle || this.props.bsStyle, - key: child.props.key, - ref: child.props.ref - }; - - if (this.props.accordion) { - props.collapsable = true; - props.expanded = (child.props.key === activeKey); - props.onSelect = this.handleSelect; - } - - return cloneWithProps( - child, - props - ); - }, - - shouldComponentUpdate: function() { - // Defer any updates to this component during the `onSelect` handler. - return !this._isChanging; - }, - - handleSelect: function (key) { - if (this.props.onSelect) { - this._isChanging = true; - this.props.onSelect(key); - this._isChanging = false; - } - - if (this.state.activeKey === key) { - key = null; - } - - this.setState({ - activeKey: key - }); - } -}); - -module.exports = PanelGroup; -}); - -define('Accordion',['require','exports','module','react','./PanelGroup'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var PanelGroup = require('./PanelGroup'); - -var Accordion = React.createClass({displayName: 'Accordion', - render: function () { - return this.transferPropsTo( - PanelGroup( {accordion:true}, - this.props.children - ) - ); - } -}); - -module.exports = Accordion; -}); - -define('utils/domUtils',['require','exports','module'],function (require, exports, module) { -/** - * Shortcut to compute element style - * - * @param {HTMLElement} elem - * @returns {CssStyle} - */ -function getComputedStyles(elem) { - return elem.ownerDocument.defaultView.getComputedStyle(elem, null); -} - -/** - * Get elements offset - * - * TODO: REMOVE JQUERY! - * - * @param {HTMLElement} DOMNode - * @returns {{top: number, left: number}} - */ -function getOffset(DOMNode) { - if (window.jQuery) { - return window.jQuery(DOMNode).offset(); - } - - var docElem = document.documentElement; - var box = { top: 0, left: 0 }; - - // If we don't have gBCR, just use 0,0 rather than error - // BlackBerry 5, iOS 3 (original iPhone) - if ( typeof DOMNode.getBoundingClientRect !== 'undefined' ) { - box = DOMNode.getBoundingClientRect(); - } - - return { - top: box.top + window.pageYOffset - docElem.clientTop, - left: box.left + window.pageXOffset - docElem.clientLeft - }; -} - -/** - * Get elements position - * - * TODO: REMOVE JQUERY! - * - * @param {HTMLElement} elem - * @param {HTMLElement?} offsetParent - * @returns {{top: number, left: number}} - */ -function getPosition(elem, offsetParent) { - if (window.jQuery) { - return window.jQuery(elem).position(); - } - - var offset, - parentOffset = {top: 0, left: 0}; - - // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent - if (getComputedStyles(elem).position === 'fixed' ) { - // We assume that getBoundingClientRect is available when computed position is fixed - offset = elem.getBoundingClientRect(); - - } else { - if (!offsetParent) { - // Get *real* offsetParent - offsetParent = offsetParent(elem); - } - - // Get correct offsets - offset = getOffset(elem); - if ( offsetParent.nodeName !== 'HTML') { - parentOffset = getOffset(offsetParent); - } - - // Add offsetParent borders - parentOffset.top += parseInt(getComputedStyles(offsetParent).borderTopWidth, 10); - parentOffset.left += parseInt(getComputedStyles(offsetParent).borderLeftWidth, 10); - } - - // Subtract parent offsets and element margins - return { - top: offset.top - parentOffset.top - parseInt(getComputedStyles(elem).marginTop, 10), - left: offset.left - parentOffset.left - parseInt(getComputedStyles(elem).marginLeft, 10) - }; -} - -/** - * Get parent element - * - * @param {HTMLElement?} elem - * @returns {HTMLElement} - */ -function offsetParent(elem) { - var docElem = document.documentElement; - var offsetParent = elem.offsetParent || docElem; - - while ( offsetParent && ( offsetParent.nodeName !== 'HTML' && - getComputedStyles(offsetParent).position === 'static' ) ) { - offsetParent = offsetParent.offsetParent; - } - - return offsetParent || docElem; -} - -module.exports = { - getComputedStyles: getComputedStyles, - getOffset: getOffset, - getPosition: getPosition, - offsetParent: offsetParent -}; -}); - -define('utils/EventListener',['require','exports','module'],function (require, exports, module) {/** - * React EventListener.listen - * - * Copyright 2013-2014 Facebook, Inc. - * @licence https://github.com/facebook/react/blob/0.11-stable/LICENSE - * - * This file contains a modified version of: - * https://github.com/facebook/react/blob/0.11-stable/src/vendor/stubs/EventListener.js - * - * TODO: remove in favour of solution provided by: - * https://github.com/facebook/react/issues/285 - */ - -/** - * Does not take into account specific nature of platform. - */ -var EventListener = { - /** - * Listen to DOM events during the bubble phase. - * - * @param {DOMEventTarget} target DOM element to register listener on. - * @param {string} eventType Event type, e.g. 'click' or 'mouseover'. - * @param {function} callback Callback function. - * @return {object} Object with a `remove` method. - */ - listen: function(target, eventType, callback) { - if (target.addEventListener) { - target.addEventListener(eventType, callback, false); - return { - remove: function() { - target.removeEventListener(eventType, callback, false); - } - }; - } else if (target.attachEvent) { - target.attachEvent('on' + eventType, callback); - return { - remove: function() { - target.detachEvent('on' + eventType, callback); - } - }; - } - } -}; - -module.exports = EventListener; - -}); - -define('AffixMixin',['require','exports','module','react','./utils/domUtils','./utils/EventListener'],function (require, exports, module) {/* global window, document */ - -var React = require('react'); -var domUtils = require('./utils/domUtils'); -var EventListener = require('./utils/EventListener'); - -var AffixMixin = { - propTypes: { - offset: React.PropTypes.number, - offsetTop: React.PropTypes.number, - offsetBottom: React.PropTypes.number - }, - - getInitialState: function () { - return { - affixClass: 'affix-top' - }; - }, - - getPinnedOffset: function (DOMNode) { - if (this.pinnedOffset) { - return this.pinnedOffset; - } - - DOMNode.className = DOMNode.className.replace(/affix-top|affix-bottom|affix/, ''); - DOMNode.className += DOMNode.className.length ? ' affix' : 'affix'; - - this.pinnedOffset = domUtils.getOffset(DOMNode).top - window.pageYOffset; - - return this.pinnedOffset; - }, - - checkPosition: function () { - var DOMNode, scrollHeight, scrollTop, position, offsetTop, offsetBottom, - affix, affixType, affixPositionTop; - - // TODO: or not visible - if (!this.isMounted()) { - return; - } - - DOMNode = this.getDOMNode(); - scrollHeight = document.documentElement.offsetHeight; - scrollTop = window.pageYOffset; - position = domUtils.getOffset(DOMNode); - offsetTop; - offsetBottom; - - if (this.affixed === 'top') { - position.top += scrollTop; - } - - offsetTop = this.props.offsetTop != null ? - this.props.offsetTop : this.props.offset; - offsetBottom = this.props.offsetBottom != null ? - this.props.offsetBottom : this.props.offset; - - if (offsetTop == null && offsetBottom == null) { - return; - } - if (offsetTop == null) { - offsetTop = 0; - } - if (offsetBottom == null) { - offsetBottom = 0; - } - - if (this.unpin != null && (scrollTop + this.unpin <= position.top)) { - affix = false; - } else if (offsetBottom != null && (position.top + DOMNode.offsetHeight >= scrollHeight - offsetBottom)) { - affix = 'bottom'; - } else if (offsetTop != null && (scrollTop <= offsetTop)) { - affix = 'top'; - } else { - affix = false; - } - - if (this.affixed === affix) { - return; - } - - if (this.unpin != null) { - DOMNode.style.top = ''; - } - - affixType = 'affix' + (affix ? '-' + affix : ''); - - this.affixed = affix; - this.unpin = affix === 'bottom' ? - this.getPinnedOffset(DOMNode) : null; - - if (affix === 'bottom') { - DOMNode.className = DOMNode.className.replace(/affix-top|affix-bottom|affix/, 'affix-bottom'); - affixPositionTop = scrollHeight - offsetBottom - DOMNode.offsetHeight - domUtils.getOffset(DOMNode).top; - } - - this.setState({ - affixClass: affixType, - affixPositionTop: affixPositionTop - }); - }, - - checkPositionWithEventLoop: function () { - setTimeout(this.checkPosition, 0); - }, - - componentDidMount: function () { - this._onWindowScrollListener = - EventListener.listen(window, 'scroll', this.checkPosition); - this._onDocumentClickListener = - EventListener.listen(document, 'click', this.checkPositionWithEventLoop); - }, - - componentWillUnmount: function () { - if (this._onWindowScrollListener) { - this._onWindowScrollListener.remove(); - } - - if (this._onDocumentClickListener) { - this._onDocumentClickListener.remove(); - } - }, - - componentDidUpdate: function (prevProps, prevState) { - if (prevState.affixClass === this.state.affixClass) { - this.checkPositionWithEventLoop(); - } - } -}; - -module.exports = AffixMixin; -}); - -define('Affix',['require','exports','module','react','./AffixMixin','./utils/domUtils'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var AffixMixin = require('./AffixMixin'); -var domUtils = require('./utils/domUtils'); - -var Affix = React.createClass({displayName: 'Affix', - statics: { - domUtils: domUtils - }, - - mixins: [AffixMixin], - - render: function () { - var holderStyle = {top: this.state.affixPositionTop}; - return this.transferPropsTo( - React.DOM.div( {className:this.state.affixClass, style:holderStyle}, - this.props.children - ) - ); - } -}); - -module.exports = Affix; -}); - -define('Alert',['require','exports','module','react','./utils/classSet','./BootstrapMixin'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var BootstrapMixin = require('./BootstrapMixin'); - - -var Alert = React.createClass({displayName: 'Alert', - mixins: [BootstrapMixin], - - propTypes: { - onDismiss: React.PropTypes.func, - dismissAfter: React.PropTypes.number - }, - - getDefaultProps: function () { - return { - bsClass: 'alert', - bsStyle: 'info' - }; - }, - - renderDismissButton: function () { - return ( - React.DOM.button( - {type:"button", - className:"close", - onClick:this.props.onDismiss, - 'aria-hidden':"true"}, - " × " - ) - ); - }, - - render: function () { - var classes = this.getBsClassSet(); - var isDismissable = !!this.props.onDismiss; - - classes['alert-dismissable'] = isDismissable; - - return this.transferPropsTo( - React.DOM.div( {className:classSet(classes)}, - isDismissable ? this.renderDismissButton() : null, - this.props.children - ) - ); - }, - - componentDidMount: function() { - if (this.props.dismissAfter && this.props.onDismiss) { - this.dismissTimer = setTimeout(this.props.onDismiss, this.props.dismissAfter); - } - }, - - componentWillUnmount: function() { - clearTimeout(this.dismissTimer); - } -}); - -module.exports = Alert; -}); - -define('Badge',['require','exports','module','react','./utils/ValidComponentChildren','./utils/classSet'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var ValidComponentChildren = require('./utils/ValidComponentChildren'); -var classSet = require('./utils/classSet'); - -var Badge = React.createClass({displayName: 'Badge', - propTypes: { - pullRight: React.PropTypes.bool, - }, - - render: function () { - var classes = { - 'pull-right': this.props.pullRight, - 'badge': ValidComponentChildren.hasValidComponent(this.props.children) - }; - return this.transferPropsTo( - React.DOM.span( {className:classSet(classes)}, - this.props.children - ) - ); - } -}); - -module.exports = Badge; - -}); - -define('utils/CustomPropTypes',['require','exports','module','react'],function (require, exports, module) {var React = require('react'); - -var ANONYMOUS = '<<anonymous>>'; - -var CustomPropTypes = { - /** - * Checks whether a prop is a valid React class - * - * @param props - * @param propName - * @param componentName - * @returns {Error|undefined} - */ - componentClass: createComponentClassChecker(), - - /** - * Checks whether a prop provides a DOM element - * - * The element can be provided in two forms: - * - Directly passed - * - Or passed an object which has a `getDOMNode` method which will return the required DOM element - * - * @param props - * @param propName - * @param componentName - * @returns {Error|undefined} - */ - mountable: createMountableChecker() -}; - -/** - * Create chain-able isRequired validator - * - * Largely copied directly from: - * https://github.com/facebook/react/blob/0.11-stable/src/core/ReactPropTypes.js#L94 - */ -function createChainableTypeChecker(validate) { - function checkType(isRequired, props, propName, componentName) { - componentName = componentName || ANONYMOUS; - if (props[propName] == null) { - if (isRequired) { - return new Error( - 'Required prop `' + propName + '` was not specified in ' + - '`' + componentName + '`.' - ); - } - } else { - return validate(props, propName, componentName); - } - } - - var chainedCheckType = checkType.bind(null, false); - chainedCheckType.isRequired = checkType.bind(null, true); - - return chainedCheckType; -} - -function createComponentClassChecker() { - function validate(props, propName, componentName) { - if (!React.isValidClass(props[propName])) { - return new Error( - 'Invalid prop `' + propName + '` supplied to ' + - '`' + componentName + '`, expected a valid React class.' - ); - } - } - - return createChainableTypeChecker(validate); -} - -function createMountableChecker() { - function validate(props, propName, componentName) { - if (typeof props[propName] !== 'object' || - typeof props[propName].getDOMNode !== 'function' && props[propName].nodeType !== 1) { - return new Error( - 'Invalid prop `' + propName + '` supplied to ' + - '`' + componentName + '`, expected a DOM element or an object that has a `getDOMNode` method' - ); - } - } - - return createChainableTypeChecker(validate); -} - -module.exports = CustomPropTypes; -}); - -define('Button',['require','exports','module','react','./utils/classSet','./BootstrapMixin','./utils/CustomPropTypes'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var BootstrapMixin = require('./BootstrapMixin'); -var CustomPropTypes = require('./utils/CustomPropTypes'); - -var Button = React.createClass({displayName: 'Button', - mixins: [BootstrapMixin], - - propTypes: { - active: React.PropTypes.bool, - disabled: React.PropTypes.bool, - block: React.PropTypes.bool, - navItem: React.PropTypes.bool, - navDropdown: React.PropTypes.bool, - componentClass: CustomPropTypes.componentClass - }, - - getDefaultProps: function () { - return { - bsClass: 'button', - bsStyle: 'default', - type: 'button' - }; - }, - - render: function () { - var classes = this.props.navDropdown ? {} : this.getBsClassSet(); - var renderFuncName; - - classes['active'] = this.props.active; - classes['btn-block'] = this.props.block; - - if (this.props.navItem) { - return this.renderNavItem(classes); - } - - renderFuncName = this.props.href || this.props.navDropdown ? - 'renderAnchor' : 'renderButton'; - - return this[renderFuncName](classes); - }, - - renderAnchor: function (classes) { - var component = this.props.componentClass || React.DOM.a; - var href = this.props.href || '#'; - classes['disabled'] = this.props.disabled; - - return this.transferPropsTo( - component( - {href:href, - className:classSet(classes), - role:"button"}, - this.props.children - ) - ); - }, - - renderButton: function (classes) { - var component = this.props.componentClass || React.DOM.button; - - return this.transferPropsTo( - component( - {className:classSet(classes)}, - this.props.children - ) - ); - }, - - renderNavItem: function (classes) { - var liClasses = { - active: this.props.active - }; - - return ( - React.DOM.li( {className:classSet(liClasses)}, - this.renderAnchor(classes) - ) - ); - } -}); - -module.exports = Button; - -}); - -define('ButtonGroup',['require','exports','module','react','./utils/classSet','./BootstrapMixin','./Button'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var BootstrapMixin = require('./BootstrapMixin'); -var Button = require('./Button'); - -var ButtonGroup = React.createClass({displayName: 'ButtonGroup', - mixins: [BootstrapMixin], - - propTypes: { - vertical: React.PropTypes.bool, - justified: React.PropTypes.bool - }, - - getDefaultProps: function () { - return { - bsClass: 'button-group' - }; - }, - - render: function () { - var classes = this.getBsClassSet(); - classes['btn-group'] = !this.props.vertical; - classes['btn-group-vertical'] = this.props.vertical; - classes['btn-group-justified'] = this.props.justified; - - return this.transferPropsTo( - React.DOM.div( - {className:classSet(classes)}, - this.props.children - ) - ); - } -}); - -module.exports = ButtonGroup; -}); - -define('ButtonToolbar',['require','exports','module','react','./utils/classSet','./BootstrapMixin','./Button'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var BootstrapMixin = require('./BootstrapMixin'); -var Button = require('./Button'); - -var ButtonToolbar = React.createClass({displayName: 'ButtonToolbar', - mixins: [BootstrapMixin], - - getDefaultProps: function () { - return { - bsClass: 'button-toolbar' - }; - }, - - render: function () { - var classes = this.getBsClassSet(); - - return this.transferPropsTo( - React.DOM.div( - {role:"toolbar", - className:classSet(classes)}, - this.props.children - ) - ); - } -}); - -module.exports = ButtonToolbar; -}); - -define('Carousel',['require','exports','module','react','./utils/classSet','./utils/cloneWithProps','./BootstrapMixin','./utils/ValidComponentChildren'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var cloneWithProps = require('./utils/cloneWithProps'); -var BootstrapMixin = require('./BootstrapMixin'); -var ValidComponentChildren = require('./utils/ValidComponentChildren'); - -var Carousel = React.createClass({displayName: 'Carousel', - mixins: [BootstrapMixin], - - propTypes: { - slide: React.PropTypes.bool, - indicators: React.PropTypes.bool, - controls: React.PropTypes.bool, - pauseOnHover: React.PropTypes.bool, - wrap: React.PropTypes.bool, - onSelect: React.PropTypes.func, - onSlideEnd: React.PropTypes.func, - activeIndex: React.PropTypes.number, - defaultActiveIndex: React.PropTypes.number, - direction: React.PropTypes.oneOf(['prev', 'next']) - }, - - getDefaultProps: function () { - return { - slide: true, - interval: 5000, - pauseOnHover: true, - wrap: true, - indicators: true, - controls: true - }; - }, - - getInitialState: function () { - return { - activeIndex: this.props.defaultActiveIndex == null ? - 0 : this.props.defaultActiveIndex, - previousActiveIndex: null, - direction: null - }; - }, - - getDirection: function (prevIndex, index) { - if (prevIndex === index) { - return null; - } - - return prevIndex > index ? - 'prev' : 'next'; - }, - - componentWillReceiveProps: function (nextProps) { - var activeIndex = this.getActiveIndex(); - - if (nextProps.activeIndex != null && nextProps.activeIndex !== activeIndex) { - clearTimeout(this.timeout); - this.setState({ - previousActiveIndex: activeIndex, - direction: nextProps.direction != null ? - nextProps.direction : this.getDirection(activeIndex, nextProps.activeIndex) - }); - } - }, - - componentDidMount: function () { - this.waitForNext(); - }, - - componentWillUnmount: function() { - clearTimeout(this.timeout); - }, - - next: function (e) { - if (e) { - e.preventDefault(); - } - - var index = this.getActiveIndex() + 1; - var count = ValidComponentChildren.numberOf(this.props.children); - - if (index > count - 1) { - if (!this.props.wrap) { - return; - } - index = 0; - } - - this.handleSelect(index, 'next'); - }, - - prev: function (e) { - if (e) { - e.preventDefault(); - } - - var index = this.getActiveIndex() - 1; - - if (index < 0) { - if (!this.props.wrap) { - return; - } - index = ValidComponentChildren.numberOf(this.props.children) - 1; - } - - this.handleSelect(index, 'prev'); - }, - - pause: function () { - this.isPaused = true; - clearTimeout(this.timeout); - }, - - play: function () { - this.isPaused = false; - this.waitForNext(); - }, - - waitForNext: function () { - if (!this.isPaused && this.props.slide && this.props.interval && - this.props.activeIndex == null) { - this.timeout = setTimeout(this.next, this.props.interval); - } - }, - - handleMouseOver: function () { - if (this.props.pauseOnHover) { - this.pause(); - } - }, - - handleMouseOut: function () { - if (this.isPaused) { - this.play(); - } - }, - - render: function () { - var classes = { - carousel: true, - slide: this.props.slide - }; - - return this.transferPropsTo( - React.DOM.div( - {className:classSet(classes), - onMouseOver:this.handleMouseOver, - onMouseOut:this.handleMouseOut}, - this.props.indicators ? this.renderIndicators() : null, - React.DOM.div( {className:"carousel-inner", ref:"inner"}, - ValidComponentChildren.map(this.props.children, this.renderItem) - ), - this.props.controls ? this.renderControls() : null - ) - ); - }, - - renderPrev: function () { - return ( - React.DOM.a( {className:"left carousel-control", href:"#prev", key:0, onClick:this.prev}, - React.DOM.span( {className:"glyphicon glyphicon-chevron-left"} ) - ) - ); - }, - - renderNext: function () { - return ( - React.DOM.a( {className:"right carousel-control", href:"#next", key:1, onClick:this.next}, - React.DOM.span( {className:"glyphicon glyphicon-chevron-right"}) - ) - ); - }, - - renderControls: function () { - if (this.props.wrap) { - var activeIndex = this.getActiveIndex(); - var count = ValidComponentChildren.numberOf(this.props.children); - - return [ - (activeIndex !== 0) ? this.renderPrev() : null, - (activeIndex !== count - 1) ? this.renderNext() : null - ]; - } - - return [ - this.renderPrev(), - this.renderNext() - ]; - }, - - renderIndicator: function (child, index) { - var className = (index === this.getActiveIndex()) ? - 'active' : null; - - return ( - React.DOM.li( - {key:index, - className:className, - onClick:this.handleSelect.bind(this, index, null)} ) - ); - }, - - renderIndicators: function () { - var indicators = []; - ValidComponentChildren - .forEach(this.props.children, function(child, index) { - indicators.push( - this.renderIndicator(child, index), - - // Force whitespace between indicator elements, bootstrap - // requires this for correct spacing of elements. - ' ' - ); - }, this); - - return ( - React.DOM.ol( {className:"carousel-indicators"}, - indicators - ) - ); - }, - - getActiveIndex: function () { - return this.props.activeIndex != null ? this.props.activeIndex : this.state.activeIndex; - }, - - handleItemAnimateOutEnd: function () { - this.setState({ - previousActiveIndex: null, - direction: null - }, function() { - this.waitForNext(); - - if (this.props.onSlideEnd) { - this.props.onSlideEnd(); - } - }); - }, - - renderItem: function (child, index) { - var activeIndex = this.getActiveIndex(); - var isActive = (index === activeIndex); - var isPreviousActive = this.state.previousActiveIndex != null && - this.state.previousActiveIndex === index && this.props.slide; - - return cloneWithProps( - child, - { - active: isActive, - ref: child.props.ref, - key: child.props.key != null ? - child.props.key : index, - index: index, - animateOut: isPreviousActive, - animateIn: isActive && this.state.previousActiveIndex != null && this.props.slide, - direction: this.state.direction, - onAnimateOutEnd: isPreviousActive ? this.handleItemAnimateOutEnd: null - } - ); - }, - - handleSelect: function (index, direction) { - clearTimeout(this.timeout); - - var previousActiveIndex = this.getActiveIndex(); - direction = direction || this.getDirection(previousActiveIndex, index); - - if (this.props.onSelect) { - this.props.onSelect(index, direction); - } - - if (this.props.activeIndex == null && index !== previousActiveIndex) { - if (this.state.previousActiveIndex != null) { - // If currently animating don't activate the new index. - // TODO: look into queuing this canceled call and - // animating after the current animation has ended. - return; - } - - this.setState({ - activeIndex: index, - previousActiveIndex: previousActiveIndex, - direction: direction - }); - } - } -}); - -module.exports = Carousel; -}); - -define('utils/TransitionEvents',['require','exports','module'],function (require, exports, module) {/** - * React TransitionEvents - * - * Copyright 2013-2014 Facebook, Inc. - * @licence https://github.com/facebook/react/blob/0.11-stable/LICENSE - * - * This file contains a modified version of: - * https://github.com/facebook/react/blob/0.11-stable/src/addons/transitions/ReactTransitionEvents.js - * - */ - -var canUseDOM = !!( - typeof window !== 'undefined' && - window.document && - window.document.createElement - ); - -/** - * EVENT_NAME_MAP is used to determine which event fired when a - * transition/animation ends, based on the style property used to - * define that event. - */ -var EVENT_NAME_MAP = { - transitionend: { - 'transition': 'transitionend', - 'WebkitTransition': 'webkitTransitionEnd', - 'MozTransition': 'mozTransitionEnd', - 'OTransition': 'oTransitionEnd', - 'msTransition': 'MSTransitionEnd' - }, - - animationend: { - 'animation': 'animationend', - 'WebkitAnimation': 'webkitAnimationEnd', - 'MozAnimation': 'mozAnimationEnd', - 'OAnimation': 'oAnimationEnd', - 'msAnimation': 'MSAnimationEnd' - } -}; - -var endEvents = []; - -function detectEvents() { - var testEl = document.createElement('div'); - var style = testEl.style; - - // On some platforms, in particular some releases of Android 4.x, - // the un-prefixed "animation" and "transition" properties are defined on the - // style object but the events that fire will still be prefixed, so we need - // to check if the un-prefixed events are useable, and if not remove them - // from the map - if (!('AnimationEvent' in window)) { - delete EVENT_NAME_MAP.animationend.animation; - } - - if (!('TransitionEvent' in window)) { - delete EVENT_NAME_MAP.transitionend.transition; - } - - for (var baseEventName in EVENT_NAME_MAP) { - var baseEvents = EVENT_NAME_MAP[baseEventName]; - for (var styleName in baseEvents) { - if (styleName in style) { - endEvents.push(baseEvents[styleName]); - break; - } - } - } -} - -if (canUseDOM) { - detectEvents(); -} - -// We use the raw {add|remove}EventListener() call because EventListener -// does not know how to remove event listeners and we really should -// clean up. Also, these events are not triggered in older browsers -// so we should be A-OK here. - -function addEventListener(node, eventName, eventListener) { - node.addEventListener(eventName, eventListener, false); -} - -function removeEventListener(node, eventName, eventListener) { - node.removeEventListener(eventName, eventListener, false); -} - -var ReactTransitionEvents = { - addEndEventListener: function(node, eventListener) { - if (endEvents.length === 0) { - // If CSS transitions are not supported, trigger an "end animation" - // event immediately. - window.setTimeout(eventListener, 0); - return; - } - endEvents.forEach(function(endEvent) { - addEventListener(node, endEvent, eventListener); - }); - }, - - removeEndEventListener: function(node, eventListener) { - if (endEvents.length === 0) { - return; - } - endEvents.forEach(function(endEvent) { - removeEventListener(node, endEvent, eventListener); - }); - } -}; - -module.exports = ReactTransitionEvents; - -}); - -define('CarouselItem',['require','exports','module','react','./utils/classSet','./utils/TransitionEvents'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var TransitionEvents = require('./utils/TransitionEvents'); - -var CarouselItem = React.createClass({displayName: 'CarouselItem', - propTypes: { - direction: React.PropTypes.oneOf(['prev', 'next']), - onAnimateOutEnd: React.PropTypes.func, - active: React.PropTypes.bool, - caption: React.PropTypes.renderable - }, - - getInitialState: function () { - return { - direction: null - }; - }, - - getDefaultProps: function () { - return { - animation: true - }; - }, - - handleAnimateOutEnd: function () { - if (this.props.onAnimateOutEnd && this.isMounted()) { - this.props.onAnimateOutEnd(this.props.index); - } - }, - - componentWillReceiveProps: function (nextProps) { - if (this.props.active !== nextProps.active) { - this.setState({ - direction: null - }); - } - }, - - componentDidUpdate: function (prevProps) { - if (!this.props.active && prevProps.active) { - TransitionEvents.addEndEventListener( - this.getDOMNode(), - this.handleAnimateOutEnd - ); - } - - if (this.props.active !== prevProps.active) { - setTimeout(this.startAnimation, 20); - } - }, - - startAnimation: function () { - if (!this.isMounted()) { - return; - } - - this.setState({ - direction: this.props.direction === 'prev' ? - 'right' : 'left' - }); - }, - - render: function () { - var classes = { - item: true, - active: (this.props.active && !this.props.animateIn) || this.props.animateOut, - next: this.props.active && this.props.animateIn && this.props.direction === 'next', - prev: this.props.active && this.props.animateIn && this.props.direction === 'prev' - }; - - if (this.state.direction && (this.props.animateIn || this.props.animateOut)) { - classes[this.state.direction] = true; - } - - return this.transferPropsTo( - React.DOM.div( {className:classSet(classes)}, - this.props.children, - this.props.caption ? this.renderCaption() : null - ) - ); - }, - - renderCaption: function () { - return ( - React.DOM.div( {className:"carousel-caption"}, - this.props.caption - ) - ); - } -}); - -module.exports = CarouselItem; -}); - -define('Col',['require','exports','module','react','./utils/classSet','./utils/CustomPropTypes','./constants'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var CustomPropTypes = require('./utils/CustomPropTypes'); -var constants = require('./constants'); - - -var Col = React.createClass({displayName: 'Col', - propTypes: { - xs: React.PropTypes.number, - sm: React.PropTypes.number, - md: React.PropTypes.number, - lg: React.PropTypes.number, - xsOffset: React.PropTypes.number, - smOffset: React.PropTypes.number, - mdOffset: React.PropTypes.number, - lgOffset: React.PropTypes.number, - xsPush: React.PropTypes.number, - smPush: React.PropTypes.number, - mdPush: React.PropTypes.number, - lgPush: React.PropTypes.number, - xsPull: React.PropTypes.number, - smPull: React.PropTypes.number, - mdPull: React.PropTypes.number, - lgPull: React.PropTypes.number, - componentClass: CustomPropTypes.componentClass.isRequired - }, - - getDefaultProps: function () { - return { - componentClass: React.DOM.div - }; - }, - - render: function () { - var componentClass = this.props.componentClass; - var classes = {}; - - Object.keys(constants.SIZES).forEach(function (key) { - var size = constants.SIZES[key]; - var prop = size; - var classPart = size + '-'; - - if (this.props[prop]) { - classes['col-' + classPart + this.props[prop]] = true; - } - - prop = size + 'Offset'; - classPart = size + '-offset-'; - if (this.props[prop]) { - classes['col-' + classPart + this.props[prop]] = true; - } - - prop = size + 'Push'; - classPart = size + '-push-'; - if (this.props[prop]) { - classes['col-' + classPart + this.props[prop]] = true; - } - - prop = size + 'Pull'; - classPart = size + '-pull-'; - if (this.props[prop]) { - classes['col-' + classPart + this.props[prop]] = true; - } - }, this); - - return this.transferPropsTo( - componentClass( {className:classSet(classes)}, - this.props.children - ) - ); - } -}); - -module.exports = Col; -}); - -define('CollapsableMixin',['require','exports','module','react','./utils/TransitionEvents'],function (require, exports, module) {var React = require('react'); -var TransitionEvents = require('./utils/TransitionEvents'); - -var CollapsableMixin = { - - propTypes: { - collapsable: React.PropTypes.bool, - defaultExpanded: React.PropTypes.bool, - expanded: React.PropTypes.bool - }, - - getInitialState: function () { - return { - expanded: this.props.defaultExpanded != null ? this.props.defaultExpanded : null, - collapsing: false - }; - }, - - handleTransitionEnd: function () { - this._collapseEnd = true; - this.setState({ - collapsing: false - }); - }, - - componentWillReceiveProps: function (newProps) { - if (this.props.collapsable && newProps.expanded !== this.props.expanded) { - this._collapseEnd = false; - this.setState({ - collapsing: true - }); - } - }, - - _addEndTransitionListener: function () { - var node = this.getCollapsableDOMNode(); - - if (node) { - TransitionEvents.addEndEventListener( - node, - this.handleTransitionEnd - ); - } - }, - - _removeEndTransitionListener: function () { - var node = this.getCollapsableDOMNode(); - - if (node) { - TransitionEvents.addEndEventListener( - node, - this.handleTransitionEnd - ); - } - }, - - componentDidMount: function () { - this._afterRender(); - }, - - componentWillUnmount: function () { - this._removeEndTransitionListener(); - }, - - componentWillUpdate: function (nextProps) { - var dimension = (typeof this.getCollapsableDimension === 'function') ? - this.getCollapsableDimension() : 'height'; - var node = this.getCollapsableDOMNode(); - - this._removeEndTransitionListener(); - if (node && nextProps.expanded !== this.props.expanded && this.props.expanded) { - node.style[dimension] = this.getCollapsableDimensionValue() + 'px'; - } - }, - - componentDidUpdate: function (prevProps, prevState) { - if (this.state.collapsing !== prevState.collapsing) { - this._afterRender(); - } - }, - - _afterRender: function () { - if (!this.props.collapsable) { - return; - } - - this._addEndTransitionListener(); - setTimeout(this._updateDimensionAfterRender, 0); - }, - - _updateDimensionAfterRender: function () { - var dimension = (typeof this.getCollapsableDimension === 'function') ? - this.getCollapsableDimension() : 'height'; - var node = this.getCollapsableDOMNode(); - - if (node) { - if(this.isExpanded() && !this.state.collapsing) { - node.style[dimension] = 'auto'; - } else { - node.style[dimension] = this.isExpanded() ? - this.getCollapsableDimensionValue() + 'px' : '0px'; - } - } - }, - - isExpanded: function () { - return (this.props.expanded != null) ? - this.props.expanded : this.state.expanded; - }, - - getCollapsableClassSet: function (className) { - var classes = {}; - - if (typeof className === 'string') { - className.split(' ').forEach(function (className) { - if (className) { - classes[className] = true; - } - }); - } - - classes.collapsing = this.state.collapsing; - classes.collapse = !this.state.collapsing; - classes['in'] = this.isExpanded() && !this.state.collapsing; - - return classes; - } -}; - -module.exports = CollapsableMixin; -}); - -define('utils/createChainedFunction',['require','exports','module'],function (require, exports, module) {/** - * Safe chained function - * - * Will only create a new function if needed, - * otherwise will pass back existing functions or null. - * - * @param {function} one - * @param {function} two - * @returns {function|null} - */ -function createChainedFunction(one, two) { - var hasOne = typeof one === 'function'; - var hasTwo = typeof two === 'function'; - - if (!hasOne && !hasTwo) { return null; } - if (!hasOne) { return two; } - if (!hasTwo) { return one; } - - return function chainedFunction() { - one.apply(this, arguments); - two.apply(this, arguments); - }; -} - -module.exports = createChainedFunction; -}); - -define('DropdownStateMixin',['require','exports','module','react','./utils/EventListener'],function (require, exports, module) {var React = require('react'); -var EventListener = require('./utils/EventListener'); - -/** - * Checks whether a node is within - * a root nodes tree - * - * @param {DOMElement} node - * @param {DOMElement} root - * @returns {boolean} - */ -function isNodeInRoot(node, root) { - while (node) { - if (node === root) { - return true; - } - node = node.parentNode; - } - - return false; -} - -var DropdownStateMixin = { - getInitialState: function () { - return { - open: false - }; - }, - - setDropdownState: function (newState, onStateChangeComplete) { - if (newState) { - this.bindRootCloseHandlers(); - } else { - this.unbindRootCloseHandlers(); - } - - this.setState({ - open: newState - }, onStateChangeComplete); - }, - - handleDocumentKeyUp: function (e) { - if (e.keyCode === 27) { - this.setDropdownState(false); - } - }, - - handleDocumentClick: function (e) { - // If the click originated from within this component - // don't do anything. - if (isNodeInRoot(e.target, this.getDOMNode())) { - return; - } - - this.setDropdownState(false); - }, - - bindRootCloseHandlers: function () { - this._onDocumentClickListener = - EventListener.listen(document, 'click', this.handleDocumentClick); - this._onDocumentKeyupListener = - EventListener.listen(document, 'keyup', this.handleDocumentKeyUp); - }, - - unbindRootCloseHandlers: function () { - if (this._onDocumentClickListener) { - this._onDocumentClickListener.remove(); - } - - if (this._onDocumentKeyupListener) { - this._onDocumentKeyupListener.remove(); - } - }, - - componentWillUnmount: function () { - this.unbindRootCloseHandlers(); - } -}; - -module.exports = DropdownStateMixin; -}); - -define('DropdownMenu',['require','exports','module','react','./utils/classSet','./utils/cloneWithProps','./utils/createChainedFunction','./utils/ValidComponentChildren'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var cloneWithProps = require('./utils/cloneWithProps'); -var createChainedFunction = require('./utils/createChainedFunction'); -var ValidComponentChildren = require('./utils/ValidComponentChildren'); - -var DropdownMenu = React.createClass({displayName: 'DropdownMenu', - propTypes: { - pullRight: React.PropTypes.bool, - onSelect: React.PropTypes.func - }, - - render: function () { - var classes = { - 'dropdown-menu': true, - 'dropdown-menu-right': this.props.pullRight - }; - - return this.transferPropsTo( - React.DOM.ul( - {className:classSet(classes), - role:"menu"}, - ValidComponentChildren.map(this.props.children, this.renderMenuItem) - ) - ); - }, - - renderMenuItem: function (child) { - return cloneWithProps( - child, - { - // Capture onSelect events - onSelect: createChainedFunction(child.props.onSelect, this.props.onSelect), - - // Force special props to be transferred - key: child.props.key, - ref: child.props.ref - } - ); - } -}); - -module.exports = DropdownMenu; -}); - -define('DropdownButton',['require','exports','module','react','./utils/classSet','./utils/cloneWithProps','./utils/createChainedFunction','./BootstrapMixin','./DropdownStateMixin','./Button','./ButtonGroup','./DropdownMenu','./utils/ValidComponentChildren'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var cloneWithProps = require('./utils/cloneWithProps'); -var createChainedFunction = require('./utils/createChainedFunction'); -var BootstrapMixin = require('./BootstrapMixin'); -var DropdownStateMixin = require('./DropdownStateMixin'); -var Button = require('./Button'); -var ButtonGroup = require('./ButtonGroup'); -var DropdownMenu = require('./DropdownMenu'); -var ValidComponentChildren = require('./utils/ValidComponentChildren'); - - -var DropdownButton = React.createClass({displayName: 'DropdownButton', - mixins: [BootstrapMixin, DropdownStateMixin], - - propTypes: { - pullRight: React.PropTypes.bool, - dropup: React.PropTypes.bool, - title: React.PropTypes.renderable, - href: React.PropTypes.string, - onClick: React.PropTypes.func, - onSelect: React.PropTypes.func, - navItem: React.PropTypes.bool - }, - - render: function () { - var className = 'dropdown-toggle'; - - var renderMethod = this.props.navItem ? - 'renderNavItem' : 'renderButtonGroup'; - - return this[renderMethod]([ - this.transferPropsTo(Button( - {ref:"dropdownButton", - className:className, - onClick:this.handleDropdownClick, - key:0, - navDropdown:this.props.navItem, - navItem:null, - title:null, - pullRight:null, - dropup:null}, - this.props.title,' ', - React.DOM.span( {className:"caret"} ) - )), - DropdownMenu( - {ref:"menu", - 'aria-labelledby':this.props.id, - pullRight:this.props.pullRight, - key:1}, - ValidComponentChildren.map(this.props.children, this.renderMenuItem) - ) - ]); - }, - - renderButtonGroup: function (children) { - var groupClasses = { - 'open': this.state.open, - 'dropup': this.props.dropup - }; - - return ( - ButtonGroup( - {bsSize:this.props.bsSize, - className:classSet(groupClasses)}, - children - ) - ); - }, - - renderNavItem: function (children) { - var classes = { - 'dropdown': true, - 'open': this.state.open, - 'dropup': this.props.dropup - }; - - return ( - React.DOM.li( {className:classSet(classes)}, - children - ) - ); - }, - - renderMenuItem: function (child) { - // Only handle the option selection if an onSelect prop has been set on the - // component or it's child, this allows a user not to pass an onSelect - // handler and have the browser preform the default action. - var handleOptionSelect = this.props.onSelect || child.props.onSelect ? - this.handleOptionSelect : null; - - return cloneWithProps( - child, - { - // Capture onSelect events - onSelect: createChainedFunction(child.props.onSelect, handleOptionSelect), - - // Force special props to be transferred - key: child.props.key, - ref: child.props.ref - } - ); - }, - - handleDropdownClick: function (e) { - e.preventDefault(); - - this.setDropdownState(!this.state.open); - }, - - handleOptionSelect: function (key) { - if (this.props.onSelect) { - this.props.onSelect(key); - } - - this.setDropdownState(false); - } -}); - -module.exports = DropdownButton; -}); - -define('FadeMixin',['require','exports','module','react'],function (require, exports, module) {var React = require('react'); - -// TODO: listen for onTransitionEnd to remove el -module.exports = { - _fadeIn: function () { - var els; - - if (this.isMounted()) { - els = this.getDOMNode().querySelectorAll('.fade'); - if (els.length) { - Array.prototype.forEach.call(els, function (el) { - el.className += ' in'; - }); - } - } - }, - - _fadeOut: function () { - var els = this._fadeOutEl.querySelectorAll('.fade.in'); - - if (els.length) { - Array.prototype.forEach.call(els, function (el) { - el.className = el.className.replace(/\bin\b/, ''); - }); - } - - setTimeout(this._handleFadeOutEnd, 300); - }, - - _handleFadeOutEnd: function () { - if (this._fadeOutEl && this._fadeOutEl.parentNode) { - this._fadeOutEl.parentNode.removeChild(this._fadeOutEl); - } - }, - - componentDidMount: function () { - if (document.querySelectorAll) { - // Firefox needs delay for transition to be triggered - setTimeout(this._fadeIn, 20); - } - }, - - componentWillUnmount: function () { - var els = this.getDOMNode().querySelectorAll('.fade'); - if (els.length) { - this._fadeOutEl = document.createElement('div'); - document.body.appendChild(this._fadeOutEl); - this._fadeOutEl.appendChild(this.getDOMNode().cloneNode(true)); - // Firefox needs delay for transition to be triggered - setTimeout(this._fadeOut, 20); - } - } -}; - -}); - -define('Glyphicon',['require','exports','module','react','./utils/classSet','./BootstrapMixin','./constants'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var BootstrapMixin = require('./BootstrapMixin'); -var constants = require('./constants'); - -var Glyphicon = React.createClass({displayName: 'Glyphicon', - mixins: [BootstrapMixin], - - propTypes: { - glyph: React.PropTypes.oneOf(constants.GLYPHS).isRequired - }, - - getDefaultProps: function () { - return { - bsClass: 'glyphicon' - }; - }, - - render: function () { - var classes = this.getBsClassSet(); - - classes['glyphicon-' + this.props.glyph] = true; - - return this.transferPropsTo( - React.DOM.span( {className:classSet(classes)}, - this.props.children - ) - ); - } -}); - -module.exports = Glyphicon; -}); - -define('Grid',['require','exports','module','react','./utils/CustomPropTypes'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var CustomPropTypes = require('./utils/CustomPropTypes'); - - -var Grid = React.createClass({displayName: 'Grid', - propTypes: { - fluid: React.PropTypes.bool, - componentClass: CustomPropTypes.componentClass.isRequired - }, - - getDefaultProps: function () { - return { - componentClass: React.DOM.div - }; - }, - - render: function () { - var componentClass = this.props.componentClass; - - return this.transferPropsTo( - componentClass( {className:this.props.fluid ? 'container-fluid' : 'container'}, - this.props.children - ) - ); - } -}); - -module.exports = Grid; -}); - -define('Input',['require','exports','module','react','./utils/classSet','./Button'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var Button = require('./Button'); - -var Input = React.createClass({displayName: 'Input', - propTypes: { - type: React.PropTypes.string, - label: React.PropTypes.renderable, - help: React.PropTypes.renderable, - addonBefore: React.PropTypes.renderable, - addonAfter: React.PropTypes.renderable, - bsStyle: function(props) { - if (props.type === 'submit') { - // Return early if `type=submit` as the `Button` component - // it transfers these props to has its own propType checks. - return; - } - - return React.PropTypes.oneOf(['success', 'warning', 'error']).apply(null, arguments); - }, - hasFeedback: React.PropTypes.bool, - groupClassName: React.PropTypes.string, - wrapperClassName: React.PropTypes.string, - labelClassName: React.PropTypes.string - }, - - getInputDOMNode: function () { - return this.refs.input.getDOMNode(); - }, - - getValue: function () { - if (this.props.type === 'static') { - return this.props.value; - } - else if (this.props.type) { - return this.getInputDOMNode().value; - } - else { - throw Error('Cannot use getValue without specifying input type.'); - } - }, - - getChecked: function () { - return this.getInputDOMNode().checked; - }, - - isCheckboxOrRadio: function () { - return this.props.type === 'radio' || this.props.type === 'checkbox'; - }, - - renderInput: function () { - var input = null; - - if (!this.props.type) { - return this.props.children - } - - switch (this.props.type) { - case 'select': - input = ( - React.DOM.select( {className:"form-control", ref:"input", key:"input"}, - this.props.children - ) - ); - break; - case 'textarea': - input = React.DOM.textarea( {className:"form-control", ref:"input", key:"input"} ); - break; - case 'static': - input = ( - React.DOM.p( {className:"form-control-static", ref:"input", key:"input"}, - this.props.value - ) - ); - break; - case 'submit': - input = this.transferPropsTo( - Button( {componentClass:React.DOM.input} ) - ); - break; - default: - var className = this.isCheckboxOrRadio() ? '' : 'form-control'; - input = React.DOM.input( {className:className, ref:"input", key:"input"} ); - } - - return this.transferPropsTo(input); - }, - - renderInputGroup: function (children) { - var addonBefore = this.props.addonBefore ? ( - React.DOM.span( {className:"input-group-addon", key:"addonBefore"}, - this.props.addonBefore - ) - ) : null; - - var addonAfter = this.props.addonAfter ? ( - React.DOM.span( {className:"input-group-addon", key:"addonAfter"}, - this.props.addonAfter - ) - ) : null; - - return addonBefore || addonAfter ? ( - React.DOM.div( {className:"input-group", key:"input-group"}, - addonBefore, - children, - addonAfter - ) - ) : children; - }, - - renderIcon: function () { - var classes = { - 'glyphicon': true, - 'form-control-feedback': true, - 'glyphicon-ok': this.props.bsStyle === 'success', - 'glyphicon-warning-sign': this.props.bsStyle === 'warning', - 'glyphicon-remove': this.props.bsStyle === 'error' - }; - - return this.props.hasFeedback ? ( - React.DOM.span( {className:classSet(classes), key:"icon"} ) - ) : null; - }, - - renderHelp: function () { - return this.props.help ? ( - React.DOM.span( {className:"help-block", key:"help"}, - this.props.help - ) - ) : null; - }, - - renderCheckboxandRadioWrapper: function (children) { - var classes = { - 'checkbox': this.props.type === 'checkbox', - 'radio': this.props.type === 'radio' - }; - - return ( - React.DOM.div( {className:classSet(classes), key:"checkboxRadioWrapper"}, - children - ) - ); - }, - - renderWrapper: function (children) { - return this.props.wrapperClassName ? ( - React.DOM.div( {className:this.props.wrapperClassName, key:"wrapper"}, - children - ) - ) : children; - }, - - renderLabel: function (children) { - var classes = { - 'control-label': !this.isCheckboxOrRadio() - }; - classes[this.props.labelClassName] = this.props.labelClassName; - - return this.props.label ? ( - React.DOM.label( {htmlFor:this.props.id, className:classSet(classes), key:"label"}, - children, - this.props.label - ) - ) : children; - }, - - renderFormGroup: function (children) { - var classes = { - 'form-group': true, - 'has-feedback': this.props.hasFeedback, - 'has-success': this.props.bsStyle === 'success', - 'has-warning': this.props.bsStyle === 'warning', - 'has-error': this.props.bsStyle === 'error' - }; - classes[this.props.groupClassName] = this.props.groupClassName; - - return ( - React.DOM.div( {className:classSet(classes)}, - children - ) - ); - }, - - render: function () { - if (this.isCheckboxOrRadio()) { - return this.renderFormGroup( - this.renderWrapper([ - this.renderCheckboxandRadioWrapper( - this.renderLabel( - this.renderInput() - ) - ), - this.renderHelp() - ]) - ); - } - else { - return this.renderFormGroup([ - this.renderLabel(), - this.renderWrapper([ - this.renderInputGroup( - this.renderInput() - ), - this.renderIcon(), - this.renderHelp() - ]) - ]); - } - } -}); - -module.exports = Input; - -}); - -define('Interpolate',['require','exports','module','react','./utils/merge','./utils/ValidComponentChildren'],function (require, exports, module) {// https://www.npmjs.org/package/react-interpolate-component - - -var React = require('react'); -var merge = require('./utils/merge'); -var ValidComponentChildren = require('./utils/ValidComponentChildren'); - -var REGEXP = /\%\((.+?)\)s/; - -var Interpolate = React.createClass({ - displayName: 'Interpolate', - - propTypes: { - format: React.PropTypes.string - }, - - getDefaultProps: function() { - return { component: React.DOM.span }; - }, - - render: function() { - var format = ValidComponentChildren.hasValidComponent(this.props.children) ? this.props.children : this.props.format; - var parent = this.props.component; - var unsafe = this.props.unsafe === true; - var props = merge(this.props); - - delete props.children; - delete props.format; - delete props.component; - delete props.unsafe; - - if (unsafe) { - var content = format.split(REGEXP).reduce(function(memo, match, index) { - var html; - - if (index % 2 === 0) { - html = match; - } else { - html = props[match]; - delete props[match]; - } - - if (React.isValidComponent(html)) { - throw new Error('cannot interpolate a React component into unsafe text'); - } - - memo += html; - - return memo; - }, ''); - - props.dangerouslySetInnerHTML = { __html: content }; - - return parent(props); - } else { - var args = format.split(REGEXP).reduce(function(memo, match, index) { - var child; - - if (index % 2 === 0) { - if (match.length === 0) { - return memo; - } - - child = match; - } else { - child = props[match]; - delete props[match]; - } - - memo.push(child); - - return memo; - }, [props]); - - return parent.apply(null, args); - } - } -}); - -module.exports = Interpolate; - -}); - -define('Jumbotron',['require','exports','module','react'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); - -var Jumbotron = React.createClass({displayName: 'Jumbotron', - - render: function () { - return this.transferPropsTo( - React.DOM.div( {className:"jumbotron"}, - this.props.children - ) - ); - } -}); - -module.exports = Jumbotron; -}); - -define('Label',['require','exports','module','react','./utils/classSet','./BootstrapMixin'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var BootstrapMixin = require('./BootstrapMixin'); - -var Label = React.createClass({displayName: 'Label', - mixins: [BootstrapMixin], - - getDefaultProps: function () { - return { - bsClass: 'label', - bsStyle: 'default' - }; - }, - - render: function () { - var classes = this.getBsClassSet(); - - return this.transferPropsTo( - React.DOM.span( {className:classSet(classes)}, - this.props.children - ) - ); - } -}); - -module.exports = Label; -}); - -define('ListGroup',['require','exports','module','react','./utils/classSet','./utils/cloneWithProps','./utils/ValidComponentChildren','./utils/createChainedFunction'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var cloneWithProps = require('./utils/cloneWithProps'); -var ValidComponentChildren = require('./utils/ValidComponentChildren'); -var createChainedFunction = require('./utils/createChainedFunction'); - -var ListGroup = React.createClass({displayName: 'ListGroup', - propTypes: { - onClick: React.PropTypes.func - }, - - render: function () { - return ( - React.DOM.div( {className:"list-group"}, - ValidComponentChildren.map(this.props.children, this.renderListItem) - ) - ); - }, - - renderListItem: function (child) { - return cloneWithProps(child, { - onClick: createChainedFunction(child.props.onClick, this.props.onClick), - ref: child.props.ref, - key: child.props.key - }); - } -}); - -module.exports = ListGroup; - -}); - -define('ListGroupItem',['require','exports','module','react','./BootstrapMixin','./utils/classSet','./utils/cloneWithProps','./utils/ValidComponentChildren'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var BootstrapMixin = require('./BootstrapMixin'); -var classSet = require('./utils/classSet'); -var cloneWithProps = require('./utils/cloneWithProps'); -var ValidComponentChildren = require('./utils/ValidComponentChildren'); - -var ListGroupItem = React.createClass({displayName: 'ListGroupItem', - mixins: [BootstrapMixin], - - propTypes: { - bsStyle: React.PropTypes.oneOf(['danger','info','success','warning']), - active: React.PropTypes.any, - disabled: React.PropTypes.any, - header: React.PropTypes.renderable, - onClick: React.PropTypes.func - }, - - getDefaultProps: function () { - return { - bsClass: 'list-group-item' - }; - }, - - render: function () { - var classes = this.getBsClassSet(); - - classes['active'] = this.props.active; - classes['disabled'] = this.props.disabled; - - if (this.props.href || this.props.onClick) { - return this.renderAnchor(classes); - } else { - return this.renderSpan(classes); - } - }, - - renderSpan: function (classes) { - return this.transferPropsTo( - React.DOM.span( {className:classSet(classes)}, - this.props.header ? this.renderStructuredContent() : this.props.children - ) - ); - }, - - renderAnchor: function (classes) { - return this.transferPropsTo( - React.DOM.a( - {className:classSet(classes), - onClick:this.handleClick}, - this.props.header ? this.renderStructuredContent() : this.props.children - ) - ); - }, - - renderStructuredContent: function () { - var header; - if (React.isValidComponent(this.props.header)) { - header = cloneWithProps(this.props.header, { - className: 'list-group-item-heading' - }); - } else { - header = ( - React.DOM.h4( {className:"list-group-item-heading"}, - this.props.header - ) - ); - } - - var content = ( - React.DOM.p( {className:"list-group-item-text"}, - this.props.children - ) - ); - - return { - header: header, - content: content - }; - }, - - handleClick: function (e) { - if (this.props.onClick) { - e.preventDefault(); - this.props.onClick(this.props.key, this.props.href); - } - } -}); - -module.exports = ListGroupItem; - -}); - -define('MenuItem',['require','exports','module','react','./utils/classSet'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); - -var MenuItem = React.createClass({displayName: 'MenuItem', - propTypes: { - header: React.PropTypes.bool, - divider: React.PropTypes.bool, - href: React.PropTypes.string, - title: React.PropTypes.string, - onSelect: React.PropTypes.func - }, - - getDefaultProps: function () { - return { - href: '#' - }; - }, - - handleClick: function (e) { - if (this.props.onSelect) { - e.preventDefault(); - this.props.onSelect(this.props.key); - } - }, - - renderAnchor: function () { - return ( - React.DOM.a( {onClick:this.handleClick, href:this.props.href, title:this.props.title, tabIndex:"-1"}, - this.props.children - ) - ); - }, - - render: function () { - var classes = { - 'dropdown-header': this.props.header, - 'divider': this.props.divider - }; - - var children = null; - if (this.props.header) { - children = this.props.children; - } else if (!this.props.divider) { - children = this.renderAnchor(); - } - - return this.transferPropsTo( - React.DOM.li( {role:"presentation", title:null, href:null, className:classSet(classes)}, - children - ) - ); - } -}); - -module.exports = MenuItem; -}); - -define('Modal',['require','exports','module','react','./utils/classSet','./BootstrapMixin','./FadeMixin','./utils/EventListener'],function (require, exports, module) {/** @jsx React.DOM */ -/* global document:false */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var BootstrapMixin = require('./BootstrapMixin'); -var FadeMixin = require('./FadeMixin'); -var EventListener = require('./utils/EventListener'); - - -// TODO: -// - aria-labelledby -// - Add `modal-body` div if only one child passed in that doesn't already have it -// - Tests - -var Modal = React.createClass({displayName: 'Modal', - mixins: [BootstrapMixin, FadeMixin], - - propTypes: { - title: React.PropTypes.renderable, - backdrop: React.PropTypes.oneOf(['static', true, false]), - keyboard: React.PropTypes.bool, - closeButton: React.PropTypes.bool, - animation: React.PropTypes.bool, - onRequestHide: React.PropTypes.func.isRequired - }, - - getDefaultProps: function () { - return { - bsClass: 'modal', - backdrop: true, - keyboard: true, - animation: true, - closeButton: true - }; - }, - - render: function () { - var modalStyle = {display: 'block'}; - var dialogClasses = this.getBsClassSet(); - delete dialogClasses.modal; - dialogClasses['modal-dialog'] = true; - - var classes = { - modal: true, - fade: this.props.animation, - 'in': !this.props.animation || !document.querySelectorAll - }; - - var modal = this.transferPropsTo( - React.DOM.div( - {title:null, - tabIndex:"-1", - role:"dialog", - style:modalStyle, - className:classSet(classes), - onClick:this.props.backdrop === true ? this.handleBackdropClick : null, - ref:"modal"}, - React.DOM.div( {className:classSet(dialogClasses)}, - React.DOM.div( {className:"modal-content"}, - this.props.title ? this.renderHeader() : null, - this.props.children - ) - ) - ) - ); - - return this.props.backdrop ? - this.renderBackdrop(modal) : modal; - }, - - renderBackdrop: function (modal) { - var classes = { - 'modal-backdrop': true, - 'fade': this.props.animation - }; - - classes['in'] = !this.props.animation || !document.querySelectorAll; - - var onClick = this.props.backdrop === true ? - this.handleBackdropClick : null; - - return ( - React.DOM.div(null, - React.DOM.div( {className:classSet(classes), ref:"backdrop", onClick:onClick} ), - modal - ) - ); - }, - - renderHeader: function () { - var closeButton; - if (this.props.closeButton) { - closeButton = ( - React.DOM.button( {type:"button", className:"close", 'aria-hidden':"true", onClick:this.props.onRequestHide}, "×") - ); - } - - return ( - React.DOM.div( {className:"modal-header"}, - closeButton, - this.renderTitle() - ) - ); - }, - - renderTitle: function () { - return ( - React.isValidComponent(this.props.title) ? - this.props.title : React.DOM.h4( {className:"modal-title"}, this.props.title) - ); - }, - - iosClickHack: function () { - // IOS only allows click events to be delegated to the document on elements - // it considers 'clickable' - anchors, buttons, etc. We fake a click handler on the - // DOM nodes themselves. Remove if handled by React: https://github.com/facebook/react/issues/1169 - this.refs.modal.getDOMNode().onclick = function () {}; - this.refs.backdrop.getDOMNode().onclick = function () {}; - }, - - componentDidMount: function () { - this._onDocumentKeyupListener = - EventListener.listen(document, 'keyup', this.handleDocumentKeyUp); - - if (this.props.backdrop) { - this.iosClickHack(); - } - }, - - componentDidUpdate: function (prevProps) { - if (this.props.backdrop && this.props.backdrop !== prevProps.backdrop) { - this.iosClickHack(); - } - }, - - componentWillUnmount: function () { - this._onDocumentKeyupListener.remove(); - }, - - handleBackdropClick: function (e) { - if (e.target !== e.currentTarget) { - return; - } - - this.props.onRequestHide(); - }, - - handleDocumentKeyUp: function (e) { - if (this.props.keyboard && e.keyCode === 27) { - this.props.onRequestHide(); - } - } -}); - -module.exports = Modal; - -}); - -define('Nav',['require','exports','module','react','./BootstrapMixin','./CollapsableMixin','./utils/classSet','./utils/domUtils','./utils/cloneWithProps','./utils/ValidComponentChildren','./utils/createChainedFunction'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var BootstrapMixin = require('./BootstrapMixin'); -var CollapsableMixin = require('./CollapsableMixin'); -var classSet = require('./utils/classSet'); -var domUtils = require('./utils/domUtils'); -var cloneWithProps = require('./utils/cloneWithProps'); -var ValidComponentChildren = require('./utils/ValidComponentChildren'); -var createChainedFunction = require('./utils/createChainedFunction'); - - -var Nav = React.createClass({displayName: 'Nav', - mixins: [BootstrapMixin, CollapsableMixin], - - propTypes: { - bsStyle: React.PropTypes.oneOf(['tabs','pills']), - stacked: React.PropTypes.bool, - justified: React.PropTypes.bool, - onSelect: React.PropTypes.func, - collapsable: React.PropTypes.bool, - expanded: React.PropTypes.bool, - navbar: React.PropTypes.bool - }, - - getDefaultProps: function () { - return { - bsClass: 'nav' - }; - }, - - getCollapsableDOMNode: function () { - return this.getDOMNode(); - }, - - getCollapsableDimensionValue: function () { - var node = this.refs.ul.getDOMNode(), - height = node.offsetHeight, - computedStyles = domUtils.getComputedStyles(node); - - return height + parseInt(computedStyles.marginTop, 10) + parseInt(computedStyles.marginBottom, 10); - }, - - render: function () { - var classes = this.props.collapsable ? this.getCollapsableClassSet() : {}; - - classes['navbar-collapse'] = this.props.collapsable; - - if (this.props.navbar && !this.props.collapsable) { - return this.transferPropsTo(this.renderUl()); - } - - return this.transferPropsTo( - React.DOM.nav( {className:classSet(classes)}, - this.renderUl() - ) - ); - }, - - renderUl: function () { - var classes = this.getBsClassSet(); - - classes['nav-stacked'] = this.props.stacked; - classes['nav-justified'] = this.props.justified; - classes['navbar-nav'] = this.props.navbar; - classes['pull-right'] = this.props.pullRight; - - return ( - React.DOM.ul( {className:classSet(classes), ref:"ul"}, - ValidComponentChildren.map(this.props.children, this.renderNavItem) - ) - ); - }, - - getChildActiveProp: function (child) { - if (child.props.active) { - return true; - } - if (this.props.activeKey != null) { - if (child.props.key === this.props.activeKey) { - return true; - } - } - if (this.props.activeHref != null) { - if (child.props.href === this.props.activeHref) { - return true; - } - } - - return child.props.active; - }, - - renderNavItem: function (child) { - return cloneWithProps( - child, - { - active: this.getChildActiveProp(child), - activeKey: this.props.activeKey, - activeHref: this.props.activeHref, - onSelect: createChainedFunction(child.props.onSelect, this.props.onSelect), - ref: child.props.ref, - key: child.props.key, - navItem: true - } - ); - } -}); - -module.exports = Nav; - -}); - -define('Navbar',['require','exports','module','react','./BootstrapMixin','./utils/CustomPropTypes','./utils/classSet','./utils/cloneWithProps','./utils/ValidComponentChildren','./utils/createChainedFunction','./Nav'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var BootstrapMixin = require('./BootstrapMixin'); -var CustomPropTypes = require('./utils/CustomPropTypes'); -var classSet = require('./utils/classSet'); -var cloneWithProps = require('./utils/cloneWithProps'); -var ValidComponentChildren = require('./utils/ValidComponentChildren'); -var createChainedFunction = require('./utils/createChainedFunction'); -var Nav = require('./Nav'); - - -var Navbar = React.createClass({displayName: 'Navbar', - mixins: [BootstrapMixin], - - propTypes: { - fixedTop: React.PropTypes.bool, - fixedBottom: React.PropTypes.bool, - staticTop: React.PropTypes.bool, - inverse: React.PropTypes.bool, - fluid: React.PropTypes.bool, - role: React.PropTypes.string, - componentClass: CustomPropTypes.componentClass.isRequired, - brand: React.PropTypes.renderable, - toggleButton: React.PropTypes.renderable, - onToggle: React.PropTypes.func, - navExpanded: React.PropTypes.bool, - defaultNavExpanded: React.PropTypes.bool - }, - - getDefaultProps: function () { - return { - bsClass: 'navbar', - bsStyle: 'default', - role: 'navigation', - componentClass: React.DOM.nav - }; - }, - - getInitialState: function () { - return { - navExpanded: this.props.defaultNavExpanded - }; - }, - - shouldComponentUpdate: function() { - // Defer any updates to this component during the `onSelect` handler. - return !this._isChanging; - }, - - handleToggle: function () { - if (this.props.onToggle) { - this._isChanging = true; - this.props.onToggle(); - this._isChanging = false; - } - - this.setState({ - navOpen: !this.state.navOpen - }); - }, - - isNavOpen: function () { - return this.props.navOpen != null ? this.props.navOpen : this.state.navOpen; - }, - - render: function () { - var classes = this.getBsClassSet(); - var componentClass = this.props.componentClass; - - classes['navbar-fixed-top'] = this.props.fixedTop; - classes['navbar-fixed-bottom'] = this.props.fixedBottom; - classes['navbar-static-top'] = this.props.staticTop; - classes['navbar-inverse'] = this.props.inverse; - - return this.transferPropsTo( - componentClass( {className:classSet(classes)}, - React.DOM.div( {className:this.props.fluid ? 'container-fluid' : 'container'}, - (this.props.brand || this.props.toggleButton || this.props.toggleNavKey) ? this.renderHeader() : null, - ValidComponentChildren.map(this.props.children, this.renderChild) - ) - ) - ); - }, - - renderChild: function (child) { - return cloneWithProps(child, { - navbar: true, - collapsable: this.props.toggleNavKey != null && this.props.toggleNavKey === child.props.key, - expanded: this.props.toggleNavKey != null && this.props.toggleNavKey === child.props.key && this.isNavOpen(), - key: child.props.key, - ref: child.props.ref - }); - }, - - renderHeader: function () { - var brand; - - if (this.props.brand) { - brand = React.isValidComponent(this.props.brand) ? - cloneWithProps(this.props.brand, { - className: 'navbar-brand' - }) : React.DOM.span( {className:"navbar-brand"}, this.props.brand); - } - - return ( - React.DOM.div( {className:"navbar-header"}, - brand, - (this.props.toggleButton || this.props.toggleNavKey != null) ? this.renderToggleButton() : null - ) - ); - }, - - renderToggleButton: function () { - var children; - - if (React.isValidComponent(this.props.toggleButton)) { - return cloneWithProps(this.props.toggleButton, { - className: 'navbar-toggle', - onClick: createChainedFunction(this.handleToggle, this.props.toggleButton.props.onClick) - }); - } - - children = (this.props.toggleButton != null) ? - this.props.toggleButton : [ - React.DOM.span( {className:"sr-only", key:0}, "Toggle navigation"), - React.DOM.span( {className:"icon-bar", key:1}), - React.DOM.span( {className:"icon-bar", key:2}), - React.DOM.span( {className:"icon-bar", key:3}) - ]; - - return ( - React.DOM.button( {className:"navbar-toggle", type:"button", onClick:this.handleToggle}, - children - ) - ); - } -}); - -module.exports = Navbar; - -}); - -define('NavItem',['require','exports','module','react','./utils/classSet','./BootstrapMixin'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var BootstrapMixin = require('./BootstrapMixin'); - -var NavItem = React.createClass({displayName: 'NavItem', - mixins: [BootstrapMixin], - - propTypes: { - onSelect: React.PropTypes.func, - active: React.PropTypes.bool, - disabled: React.PropTypes.bool, - href: React.PropTypes.string, - title: React.PropTypes.string - }, - - getDefaultProps: function () { - return { - href: '#' - }; - }, - - render: function () { - var classes = { - 'active': this.props.active, - 'disabled': this.props.disabled - }; - - return this.transferPropsTo( - React.DOM.li( {className:classSet(classes)}, - React.DOM.a( - {href:this.props.href, - title:this.props.title, - onClick:this.handleClick, - ref:"anchor"}, - this.props.children - ) - ) - ); - }, - - handleClick: function (e) { - if (this.props.onSelect) { - e.preventDefault(); - - if (!this.props.disabled) { - this.props.onSelect(this.props.key,this.props.href); - } - } - } -}); - -module.exports = NavItem; -}); - -define('OverlayMixin',['require','exports','module','react','./utils/CustomPropTypes'],function (require, exports, module) {var React = require('react'); -var CustomPropTypes = require('./utils/CustomPropTypes'); - -module.exports = { - propTypes: { - container: CustomPropTypes.mountable - }, - - getDefaultProps: function () { - return { - container: { - // Provide `getDOMNode` fn mocking a React component API. The `document.body` - // reference needs to be contained within this function so that it is not accessed - // in environments where it would not be defined, e.g. nodejs. Equally this is needed - // before the body is defined where `document.body === null`, this ensures - // `document.body` is only accessed after componentDidMount. - getDOMNode: function getDOMNode() { - return document.body; - } - } - }; - }, - - componentWillUnmount: function () { - this._unrenderOverlay(); - if (this._overlayTarget) { - this.getContainerDOMNode() - .removeChild(this._overlayTarget); - this._overlayTarget = null; - } - }, - - componentDidUpdate: function () { - this._renderOverlay(); - }, - - componentDidMount: function () { - this._renderOverlay(); - }, - - _mountOverlayTarget: function () { - this._overlayTarget = document.createElement('div'); - this.getContainerDOMNode() - .appendChild(this._overlayTarget); - }, - - _renderOverlay: function () { - if (!this._overlayTarget) { - this._mountOverlayTarget(); - } - - // Save reference to help testing - this._overlayInstance = React.renderComponent(this.renderOverlay(), this._overlayTarget); - }, - - _unrenderOverlay: function () { - React.unmountComponentAtNode(this._overlayTarget); - this._overlayInstance = null; - }, - - getOverlayDOMNode: function () { - if (!this.isMounted()) { - throw new Error('getOverlayDOMNode(): A component must be mounted to have a DOM node.'); - } - - return this._overlayInstance.getDOMNode(); - }, - - getContainerDOMNode: function () { - return this.props.container.getDOMNode ? - this.props.container.getDOMNode() : this.props.container; - } -}; - -}); - -define('ModalTrigger',['require','exports','module','react','./OverlayMixin','./utils/cloneWithProps','./utils/createChainedFunction'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var OverlayMixin = require('./OverlayMixin'); -var cloneWithProps = require('./utils/cloneWithProps'); -var createChainedFunction = require('./utils/createChainedFunction'); - -var ModalTrigger = React.createClass({displayName: 'ModalTrigger', - mixins: [OverlayMixin], - - propTypes: { - modal: React.PropTypes.renderable.isRequired - }, - - getInitialState: function () { - return { - isOverlayShown: false - }; - }, - - show: function () { - this.setState({ - isOverlayShown: true - }); - }, - - hide: function () { - this.setState({ - isOverlayShown: false - }); - }, - - toggle: function () { - this.setState({ - isOverlayShown: !this.state.isOverlayShown - }); - }, - - renderOverlay: function () { - if (!this.state.isOverlayShown) { - return React.DOM.span(null ); - } - - return cloneWithProps( - this.props.modal, - { - onRequestHide: this.hide - } - ); - }, - - render: function () { - var child = React.Children.only(this.props.children); - return cloneWithProps( - child, - { - onClick: createChainedFunction(child.props.onClick, this.toggle) - } - ); - } -}); - -module.exports = ModalTrigger; -}); - -define('OverlayTrigger',['require','exports','module','react','./OverlayMixin','./utils/domUtils','./utils/cloneWithProps','./utils/createChainedFunction','./utils/merge'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var OverlayMixin = require('./OverlayMixin'); -var domUtils = require('./utils/domUtils'); -var cloneWithProps = require('./utils/cloneWithProps'); -var createChainedFunction = require('./utils/createChainedFunction'); -var merge = require('./utils/merge'); - -/** - * Check if value one is inside or equal to the of value - * - * @param {string} one - * @param {string|array} of - * @returns {boolean} - */ -function isOneOf(one, of) { - if (Array.isArray(of)) { - return of.indexOf(one) >= 0; - } - return one === of; -} - -var OverlayTrigger = React.createClass({displayName: 'OverlayTrigger', - mixins: [OverlayMixin], - - propTypes: { - trigger: React.PropTypes.oneOfType([ - React.PropTypes.oneOf(['manual', 'click', 'hover', 'focus']), - React.PropTypes.arrayOf(React.PropTypes.oneOf(['click', 'hover', 'focus'])) - ]), - placement: React.PropTypes.oneOf(['top','right', 'bottom', 'left']), - delay: React.PropTypes.number, - delayShow: React.PropTypes.number, - delayHide: React.PropTypes.number, - defaultOverlayShown: React.PropTypes.bool, - overlay: React.PropTypes.renderable.isRequired - }, - - getDefaultProps: function () { - return { - placement: 'right', - trigger: ['hover', 'focus'] - }; - }, - - getInitialState: function () { - return { - isOverlayShown: this.props.defaultOverlayShown == null ? - false : this.props.defaultOverlayShown, - overlayLeft: null, - overlayTop: null - }; - }, - - show: function () { - this.setState({ - isOverlayShown: true - }, function() { - this.updateOverlayPosition(); - }); - }, - - hide: function () { - this.setState({ - isOverlayShown: false - }); - }, - - toggle: function () { - this.state.isOverlayShown ? - this.hide() : this.show(); - }, - - renderOverlay: function () { - if (!this.state.isOverlayShown) { - return React.DOM.span(null ); - } - - return cloneWithProps( - this.props.overlay, - { - onRequestHide: this.hide, - placement: this.props.placement, - positionLeft: this.state.overlayLeft, - positionTop: this.state.overlayTop - } - ); - }, - - render: function () { - if (this.props.trigger === 'manual') { - return React.Children.only(this.props.children); - } - - var props = {}; - - if (isOneOf('click', this.props.trigger)) { - props.onClick = createChainedFunction(this.toggle, this.props.onClick); - } - - if (isOneOf('hover', this.props.trigger)) { - props.onMouseOver = createChainedFunction(this.handleDelayedShow, this.props.onMouseOver); - props.onMouseOut = createChainedFunction(this.handleDelayedHide, this.props.onMouseOut); - } - - if (isOneOf('focus', this.props.trigger)) { - props.onFocus = createChainedFunction(this.handleDelayedShow, this.props.onFocus); - props.onBlur = createChainedFunction(this.handleDelayedHide, this.props.onBlur); - } - - return cloneWithProps( - React.Children.only(this.props.children), - props - ); - }, - - componentWillUnmount: function() { - clearTimeout(this._hoverDelay); - }, - - handleDelayedShow: function () { - if (this._hoverDelay != null) { - clearTimeout(this._hoverDelay); - this._hoverDelay = null; - return; - } - - var delay = this.props.delayShow != null ? - this.props.delayShow : this.props.delay; - - if (!delay) { - this.show(); - return; - } - - this._hoverDelay = setTimeout(function() { - this._hoverDelay = null; - this.show(); - }.bind(this), delay); - }, - - handleDelayedHide: function () { - if (this._hoverDelay != null) { - clearTimeout(this._hoverDelay); - this._hoverDelay = null; - return; - } - - var delay = this.props.delayHide != null ? - this.props.delayHide : this.props.delay; - - if (!delay) { - this.hide(); - return; - } - - this._hoverDelay = setTimeout(function() { - this._hoverDelay = null; - this.hide(); - }.bind(this), delay); - }, - - updateOverlayPosition: function () { - if (!this.isMounted()) { - return; - } - - var pos = this.calcOverlayPosition(); - - this.setState({ - overlayLeft: pos.left, - overlayTop: pos.top - }); - }, - - calcOverlayPosition: function () { - var childOffset = this.getPosition(); - - var overlayNode = this.getOverlayDOMNode(); - var overlayHeight = overlayNode.offsetHeight; - var overlayWidth = overlayNode.offsetWidth; - - switch (this.props.placement) { - case 'right': - return { - top: childOffset.top + childOffset.height / 2 - overlayHeight / 2, - left: childOffset.left + childOffset.width - }; - case 'left': - return { - top: childOffset.top + childOffset.height / 2 - overlayHeight / 2, - left: childOffset.left - overlayWidth - }; - case 'top': - return { - top: childOffset.top - overlayHeight, - left: childOffset.left + childOffset.width / 2 - overlayWidth / 2 - }; - case 'bottom': - return { - top: childOffset.top + childOffset.height, - left: childOffset.left + childOffset.width / 2 - overlayWidth / 2 - }; - default: - throw new Error('calcOverlayPosition(): No such placement of "' + this.props.placement + '" found.'); - } - }, - - getPosition: function () { - var node = this.getDOMNode(); - var container = this.getContainerDOMNode(); - - var offset = container.tagName == 'BODY' ? - domUtils.getOffset(node) : domUtils.getPosition(node, container); - - return merge(offset, { - height: node.offsetHeight, - width: node.offsetWidth - }); - } -}); - -module.exports = OverlayTrigger; -}); - -define('PageHeader',['require','exports','module','react'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); - -var PageHeader = React.createClass({displayName: 'PageHeader', - - render: function () { - return this.transferPropsTo( - React.DOM.div( {className:"page-header"}, - React.DOM.h1(null, this.props.children) - ) - ); - } -}); - -module.exports = PageHeader; -}); - -define('Panel',['require','exports','module','react','./utils/classSet','./utils/cloneWithProps','./BootstrapMixin','./CollapsableMixin'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var cloneWithProps = require('./utils/cloneWithProps'); -var BootstrapMixin = require('./BootstrapMixin'); -var CollapsableMixin = require('./CollapsableMixin'); - -var Panel = React.createClass({displayName: 'Panel', - mixins: [BootstrapMixin, CollapsableMixin], - - propTypes: { - onSelect: React.PropTypes.func, - header: React.PropTypes.renderable, - footer: React.PropTypes.renderable - }, - - getDefaultProps: function () { - return { - bsClass: 'panel', - bsStyle: 'default' - }; - }, - - handleSelect: function (e) { - if (this.props.onSelect) { - this._isChanging = true; - this.props.onSelect(this.props.key); - this._isChanging = false; - } - - e.preventDefault(); - - this.setState({ - expanded: !this.state.expanded - }); - }, - - shouldComponentUpdate: function () { - return !this._isChanging; - }, - - getCollapsableDimensionValue: function () { - return this.refs.body.getDOMNode().offsetHeight; - }, - - getCollapsableDOMNode: function () { - if (!this.isMounted() || !this.refs || !this.refs.panel) { - return null; - } - - return this.refs.panel.getDOMNode(); - }, - - render: function () { - var classes = this.getBsClassSet(); - classes['panel'] = true; - - return this.transferPropsTo( - React.DOM.div( {className:classSet(classes), id:this.props.collapsable ? null : this.props.id, onSelect:null}, - this.renderHeading(), - this.props.collapsable ? this.renderCollapsableBody() : this.renderBody(), - this.renderFooter() - ) - ); - }, - - renderCollapsableBody: function () { - return ( - React.DOM.div( {className:classSet(this.getCollapsableClassSet('panel-collapse')), id:this.props.id, ref:"panel"}, - this.renderBody() - ) - ); - }, - - renderBody: function () { - return ( - React.DOM.div( {className:"panel-body", ref:"body"}, - this.props.children - ) - ); - }, - - renderHeading: function () { - var header = this.props.header; - - if (!header) { - return null; - } - - if (!React.isValidComponent(header) || Array.isArray(header)) { - header = this.props.collapsable ? - this.renderCollapsableTitle(header) : header; - } else if (this.props.collapsable) { - header = cloneWithProps(header, { - className: 'panel-title', - children: this.renderAnchor(header.props.children) - }); - } else { - header = cloneWithProps(header, { - className: 'panel-title' - }); - } - - return ( - React.DOM.div( {className:"panel-heading"}, - header - ) - ); - }, - - renderAnchor: function (header) { - return ( - React.DOM.a( - {href:'#' + (this.props.id || ''), - className:this.isExpanded() ? null : 'collapsed', - onClick:this.handleSelect}, - header - ) - ); - }, - - renderCollapsableTitle: function (header) { - return ( - React.DOM.h4( {className:"panel-title"}, - this.renderAnchor(header) - ) - ); - }, - - renderFooter: function () { - if (!this.props.footer) { - return null; - } - - return ( - React.DOM.div( {className:"panel-footer"}, - this.props.footer - ) - ); - } -}); - -module.exports = Panel; -}); - -define('PageItem',['require','exports','module','react','./utils/classSet'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); - -var PageItem = React.createClass({displayName: 'PageItem', - - propTypes: { - disabled: React.PropTypes.bool, - previous: React.PropTypes.bool, - next: React.PropTypes.bool, - onSelect: React.PropTypes.func - }, - - getDefaultProps: function () { - return { - href: '#' - }; - }, - - render: function () { - var classes = { - 'disabled': this.props.disabled, - 'previous': this.props.previous, - 'next': this.props.next - }; - - return this.transferPropsTo( - React.DOM.li( - {className:classSet(classes)}, - React.DOM.a( - {href:this.props.href, - title:this.props.title, - onClick:this.handleSelect, - ref:"anchor"}, - this.props.children - ) - ) - ); - }, - - handleSelect: function (e) { - if (this.props.onSelect) { - e.preventDefault(); - - if (!this.props.disabled) { - this.props.onSelect(this.props.key, this.props.href); - } - } - } -}); - -module.exports = PageItem; -}); - -define('Pager',['require','exports','module','react','./utils/cloneWithProps','./utils/ValidComponentChildren','./utils/createChainedFunction'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var cloneWithProps = require('./utils/cloneWithProps'); -var ValidComponentChildren = require('./utils/ValidComponentChildren'); -var createChainedFunction = require('./utils/createChainedFunction'); - -var Pager = React.createClass({displayName: 'Pager', - - propTypes: { - onSelect: React.PropTypes.func - }, - - render: function () { - return this.transferPropsTo( - React.DOM.ul( - {className:"pager"}, - ValidComponentChildren.map(this.props.children, this.renderPageItem) - ) - ); - }, - - renderPageItem: function (child) { - return cloneWithProps( - child, - { - onSelect: createChainedFunction(child.props.onSelect, this.props.onSelect), - ref: child.props.ref, - key: child.props.key - } - ); - } -}); - -module.exports = Pager; -}); - -define('Popover',['require','exports','module','react','./utils/classSet','./BootstrapMixin'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var BootstrapMixin = require('./BootstrapMixin'); - - -var Popover = React.createClass({displayName: 'Popover', - mixins: [BootstrapMixin], - - propTypes: { - placement: React.PropTypes.oneOf(['top','right', 'bottom', 'left']), - positionLeft: React.PropTypes.number, - positionTop: React.PropTypes.number, - arrowOffsetLeft: React.PropTypes.number, - arrowOffsetTop: React.PropTypes.number, - title: React.PropTypes.renderable - }, - - getDefaultProps: function () { - return { - placement: 'right' - }; - }, - - render: function () { - var classes = {}; - classes['popover'] = true; - classes[this.props.placement] = true; - classes['in'] = this.props.positionLeft != null || this.props.positionTop != null; - - var style = {}; - style['left'] = this.props.positionLeft; - style['top'] = this.props.positionTop; - style['display'] = 'block'; - - var arrowStyle = {}; - arrowStyle['left'] = this.props.arrowOffsetLeft; - arrowStyle['top'] = this.props.arrowOffsetTop; - - return this.transferPropsTo( - React.DOM.div( {className:classSet(classes), style:style, title:null}, - React.DOM.div( {className:"arrow", style:arrowStyle} ), - this.props.title ? this.renderTitle() : null, - React.DOM.div( {className:"popover-content"}, - this.props.children - ) - ) - ); - }, - - renderTitle: function() { - return ( - React.DOM.h3( {className:"popover-title"}, this.props.title) - ); - } -}); - -module.exports = Popover; -}); - -define('ProgressBar',['require','exports','module','react','./Interpolate','./BootstrapMixin','./utils/classSet','./utils/cloneWithProps','./utils/ValidComponentChildren'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var Interpolate = require('./Interpolate'); -var BootstrapMixin = require('./BootstrapMixin'); -var classSet = require('./utils/classSet'); -var cloneWithProps = require('./utils/cloneWithProps'); -var ValidComponentChildren = require('./utils/ValidComponentChildren'); - - -var ProgressBar = React.createClass({displayName: 'ProgressBar', - propTypes: { - min: React.PropTypes.number, - now: React.PropTypes.number, - max: React.PropTypes.number, - label: React.PropTypes.renderable, - srOnly: React.PropTypes.bool, - striped: React.PropTypes.bool, - active: React.PropTypes.bool - }, - - mixins: [BootstrapMixin], - - getDefaultProps: function () { - return { - bsClass: 'progress-bar', - min: 0, - max: 100 - }; - }, - - getPercentage: function (now, min, max) { - return Math.ceil((now - min) / (max - min) * 100); - }, - - render: function () { - var classes = { - progress: true - }; - - if (this.props.active) { - classes['progress-striped'] = true; - classes['active'] = true; - } else if (this.props.striped) { - classes['progress-striped'] = true; - } - - if (!ValidComponentChildren.hasValidComponent(this.props.children)) { - if (!this.props.isChild) { - return this.transferPropsTo( - React.DOM.div( {className:classSet(classes)}, - this.renderProgressBar() - ) - ); - } else { - return this.transferPropsTo( - this.renderProgressBar() - ); - } - } else { - return this.transferPropsTo( - React.DOM.div( {className:classSet(classes)}, - ValidComponentChildren.map(this.props.children, this.renderChildBar) - ) - ); - } - }, - - renderChildBar: function (child) { - return cloneWithProps(child, { - isChild: true, - key: child.props.key, - ref: child.props.ref - }); - }, - - renderProgressBar: function () { - var percentage = this.getPercentage( - this.props.now, - this.props.min, - this.props.max - ); - - var label; - - if (typeof this.props.label === "string") { - label = this.renderLabel(percentage); - } else if (this.props.label) { - label = this.props.label; - } - - if (this.props.srOnly) { - label = this.renderScreenReaderOnlyLabel(label); - } - - return ( - React.DOM.div( {className:classSet(this.getBsClassSet()), role:"progressbar", - style:{width: percentage + '%'}, - 'aria-valuenow':this.props.now, - 'aria-valuemin':this.props.min, - 'aria-valuemax':this.props.max}, - label - ) - ); - }, - - renderLabel: function (percentage) { - var InterpolateClass = this.props.interpolateClass || Interpolate; - - return ( - InterpolateClass( - {now:this.props.now, - min:this.props.min, - max:this.props.max, - percent:percentage, - bsStyle:this.props.bsStyle}, - this.props.label - ) - ); - }, - - renderScreenReaderOnlyLabel: function (label) { - return ( - React.DOM.span( {className:"sr-only"}, - label - ) - ); - } -}); - -module.exports = ProgressBar; - -}); - -define('Row',['require','exports','module','react','./utils/CustomPropTypes'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var CustomPropTypes = require('./utils/CustomPropTypes'); - - -var Row = React.createClass({displayName: 'Row', - propTypes: { - componentClass: CustomPropTypes.componentClass.isRequired - }, - - getDefaultProps: function () { - return { - componentClass: React.DOM.div - }; - }, - - render: function () { - var componentClass = this.props.componentClass; - - return this.transferPropsTo( - componentClass( {className:"row"}, - this.props.children - ) - ); - } -}); - -module.exports = Row; -}); - -define('SplitButton',['require','exports','module','react','./utils/classSet','./BootstrapMixin','./DropdownStateMixin','./Button','./ButtonGroup','./DropdownMenu'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var BootstrapMixin = require('./BootstrapMixin'); -var DropdownStateMixin = require('./DropdownStateMixin'); -var Button = require('./Button'); -var ButtonGroup = require('./ButtonGroup'); -var DropdownMenu = require('./DropdownMenu'); - -var SplitButton = React.createClass({displayName: 'SplitButton', - mixins: [BootstrapMixin, DropdownStateMixin], - - propTypes: { - pullRight: React.PropTypes.bool, - title: React.PropTypes.renderable, - href: React.PropTypes.string, - dropdownTitle: React.PropTypes.renderable, - onClick: React.PropTypes.func, - onSelect: React.PropTypes.func, - disabled: React.PropTypes.bool - }, - - getDefaultProps: function () { - return { - dropdownTitle: 'Toggle dropdown' - }; - }, - - render: function () { - var groupClasses = { - 'open': this.state.open, - 'dropup': this.props.dropup - }; - - var button = this.transferPropsTo( - Button( - {ref:"button", - onClick:this.handleButtonClick, - title:null, - id:null}, - this.props.title - ) - ); - - var dropdownButton = this.transferPropsTo( - Button( - {ref:"dropdownButton", - className:"dropdown-toggle", - onClick:this.handleDropdownClick, - title:null, - id:null}, - React.DOM.span( {className:"sr-only"}, this.props.dropdownTitle), - React.DOM.span( {className:"caret"} ) - ) - ); - - return ( - ButtonGroup( - {bsSize:this.props.bsSize, - className:classSet(groupClasses), - id:this.props.id}, - button, - dropdownButton, - DropdownMenu( - {ref:"menu", - onSelect:this.handleOptionSelect, - 'aria-labelledby':this.props.id, - pullRight:this.props.pullRight}, - this.props.children - ) - ) - ); - }, - - handleButtonClick: function (e) { - if (this.state.open) { - this.setDropdownState(false); - } - - if (this.props.onClick) { - this.props.onClick(e); - } - }, - - handleDropdownClick: function (e) { - e.preventDefault(); - - this.setDropdownState(!this.state.open); - }, - - handleOptionSelect: function (key) { - if (this.props.onSelect) { - this.props.onSelect(key); - } - - this.setDropdownState(false); - } -}); - -module.exports = SplitButton; - -}); - -define('SubNav',['require','exports','module','react','./utils/classSet','./utils/cloneWithProps','./utils/ValidComponentChildren','./utils/createChainedFunction','./BootstrapMixin'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var cloneWithProps = require('./utils/cloneWithProps'); -var ValidComponentChildren = require('./utils/ValidComponentChildren'); -var createChainedFunction = require('./utils/createChainedFunction'); -var BootstrapMixin = require('./BootstrapMixin'); - - -var SubNav = React.createClass({displayName: 'SubNav', - mixins: [BootstrapMixin], - - propTypes: { - onSelect: React.PropTypes.func, - active: React.PropTypes.bool, - disabled: React.PropTypes.bool, - href: React.PropTypes.string, - title: React.PropTypes.string, - text: React.PropTypes.renderable - }, - - getDefaultProps: function () { - return { - bsClass: 'nav' - }; - }, - - handleClick: function (e) { - if (this.props.onSelect) { - e.preventDefault(); - - if (!this.props.disabled) { - this.props.onSelect(this.props.key, this.props.href); - } - } - }, - - isActive: function () { - return this.isChildActive(this); - }, - - isChildActive: function (child) { - if (child.props.active) { - return true; - } - - if (this.props.activeKey != null && this.props.activeKey === child.props.key) { - return true; - } - - if (this.props.activeHref != null && this.props.activeHref === child.props.href) { - return true; - } - - if (child.props.children) { - var isActive = false; - - ValidComponentChildren.forEach( - child.props.children, - function (child) { - if (this.isChildActive(child)) { - isActive = true; - } - }, - this - ); - - return isActive; - } - - return false; - }, - - getChildActiveProp: function (child) { - if (child.props.active) { - return true; - } - if (this.props.activeKey != null) { - if (child.props.key === this.props.activeKey) { - return true; - } - } - if (this.props.activeHref != null) { - if (child.props.href === this.props.activeHref) { - return true; - } - } - - return child.props.active; - }, - - render: function () { - var classes = { - 'active': this.isActive(), - 'disabled': this.props.disabled - }; - - return this.transferPropsTo( - React.DOM.li( {className:classSet(classes)}, - React.DOM.a( - {href:this.props.href, - title:this.props.title, - onClick:this.handleClick, - ref:"anchor"}, - this.props.text - ), - React.DOM.ul( {className:"nav"}, - ValidComponentChildren.map(this.props.children, this.renderNavItem) - ) - ) - ); - }, - - renderNavItem: function (child) { - return cloneWithProps( - child, - { - active: this.getChildActiveProp(child), - onSelect: createChainedFunction(child.props.onSelect, this.props.onSelect), - ref: child.props.ref, - key: child.props.key - } - ); - } -}); - -module.exports = SubNav; - -}); - -define('TabbedArea',['require','exports','module','react','./BootstrapMixin','./utils/cloneWithProps','./utils/ValidComponentChildren','./Nav','./NavItem'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var BootstrapMixin = require('./BootstrapMixin'); -var cloneWithProps = require('./utils/cloneWithProps'); -var ValidComponentChildren = require('./utils/ValidComponentChildren'); -var Nav = require('./Nav'); -var NavItem = require('./NavItem'); - -function getDefaultActiveKeyFromChildren(children) { - var defaultActiveKey; - - ValidComponentChildren.forEach(children, function(child) { - if (defaultActiveKey == null) { - defaultActiveKey = child.props.key; - } - }); - - return defaultActiveKey; -} - -var TabbedArea = React.createClass({displayName: 'TabbedArea', - mixins: [BootstrapMixin], - - propTypes: { - bsStyle: React.PropTypes.oneOf(['tabs','pills']), - animation: React.PropTypes.bool, - onSelect: React.PropTypes.func - }, - - getDefaultProps: function () { - return { - bsStyle: "tabs", - animation: true - }; - }, - - getInitialState: function () { - var defaultActiveKey = this.props.defaultActiveKey != null ? - this.props.defaultActiveKey : getDefaultActiveKeyFromChildren(this.props.children); - - // TODO: In __DEV__ mode warn via `console.warn` if no `defaultActiveKey` has - // been set by this point, invalid children or missing key properties are likely the cause. - - return { - activeKey: defaultActiveKey, - previousActiveKey: null - }; - }, - - componentWillReceiveProps: function (nextProps) { - if (nextProps.activeKey != null && nextProps.activeKey !== this.props.activeKey) { - this.setState({ - previousActiveKey: this.props.activeKey - }); - } - }, - - handlePaneAnimateOutEnd: function () { - this.setState({ - previousActiveKey: null - }); - }, - - render: function () { - var activeKey = - this.props.activeKey != null ? this.props.activeKey : this.state.activeKey; - - function renderTabIfSet(child) { - return child.props.tab != null ? this.renderTab(child) : null; - } - - var nav = this.transferPropsTo( - Nav( {activeKey:activeKey, onSelect:this.handleSelect, ref:"tabs"}, - ValidComponentChildren.map(this.props.children, renderTabIfSet, this) - ) - ); - - return ( - React.DOM.div(null, - nav, - React.DOM.div( {id:this.props.id, className:"tab-content", ref:"panes"}, - ValidComponentChildren.map(this.props.children, this.renderPane) - ) - ) - ); - }, - - getActiveKey: function () { - return this.props.activeKey != null ? this.props.activeKey : this.state.activeKey; - }, - - renderPane: function (child) { - var activeKey = this.getActiveKey(); - - return cloneWithProps( - child, - { - active: (child.props.key === activeKey && - (this.state.previousActiveKey == null || !this.props.animation)), - ref: child.props.ref, - key: child.props.key, - animation: this.props.animation, - onAnimateOutEnd: (this.state.previousActiveKey != null && - child.props.key === this.state.previousActiveKey) ? this.handlePaneAnimateOutEnd: null - } - ); - }, - - renderTab: function (child) { - var key = child.props.key; - return ( - NavItem( - {ref:'tab' + key, - key:key}, - child.props.tab - ) - ); - }, - - shouldComponentUpdate: function() { - // Defer any updates to this component during the `onSelect` handler. - return !this._isChanging; - }, - - handleSelect: function (key) { - if (this.props.onSelect) { - this._isChanging = true; - this.props.onSelect(key); - this._isChanging = false; - } else if (key !== this.getActiveKey()) { - this.setState({ - activeKey: key, - previousActiveKey: this.getActiveKey() - }); - } - } -}); - -module.exports = TabbedArea; -}); - -define('Table',['require','exports','module','react','./utils/classSet'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); - -var Table = React.createClass({displayName: 'Table', - propTypes: { - striped: React.PropTypes.bool, - bordered: React.PropTypes.bool, - condensed: React.PropTypes.bool, - hover: React.PropTypes.bool, - responsive: React.PropTypes.bool - }, - - render: function () { - var classes = { - 'table': true, - 'table-striped': this.props.striped, - 'table-bordered': this.props.bordered, - 'table-condensed': this.props.condensed, - 'table-hover': this.props.hover - }; - var table = this.transferPropsTo( - React.DOM.table( {className:classSet(classes)}, - this.props.children - ) - ); - - return this.props.responsive ? ( - React.DOM.div( {className:"table-responsive"}, - table - ) - ) : table; - } -}); - -module.exports = Table; -}); - -define('TabPane',['require','exports','module','react','./utils/classSet','./utils/TransitionEvents'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var TransitionEvents = require('./utils/TransitionEvents'); - -var TabPane = React.createClass({displayName: 'TabPane', - getDefaultProps: function () { - return { - animation: true - }; - }, - - getInitialState: function () { - return { - animateIn: false, - animateOut: false - }; - }, - - componentWillReceiveProps: function (nextProps) { - if (this.props.animation) { - if (!this.state.animateIn && nextProps.active && !this.props.active) { - this.setState({ - animateIn: true - }); - } else if (!this.state.animateOut && !nextProps.active && this.props.active) { - this.setState({ - animateOut: true - }); - } - } - }, - - componentDidUpdate: function () { - if (this.state.animateIn) { - setTimeout(this.startAnimateIn, 0); - } - if (this.state.animateOut) { - TransitionEvents.addEndEventListener( - this.getDOMNode(), - this.stopAnimateOut - ); - } - }, - - startAnimateIn: function () { - if (this.isMounted()) { - this.setState({ - animateIn: false - }); - } - }, - - stopAnimateOut: function () { - if (this.isMounted()) { - this.setState({ - animateOut: false - }); - - if (typeof this.props.onAnimateOutEnd === 'function') { - this.props.onAnimateOutEnd(); - } - } - }, - - render: function () { - var classes = { - 'tab-pane': true, - 'fade': true, - 'active': this.props.active || this.state.animateOut, - 'in': this.props.active && !this.state.animateIn - }; - - return this.transferPropsTo( - React.DOM.div( {className:classSet(classes)}, - this.props.children - ) - ); - } -}); - -module.exports = TabPane; -}); - -define('Tooltip',['require','exports','module','react','./utils/classSet','./BootstrapMixin'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var BootstrapMixin = require('./BootstrapMixin'); - - -var Tooltip = React.createClass({displayName: 'Tooltip', - mixins: [BootstrapMixin], - - propTypes: { - placement: React.PropTypes.oneOf(['top','right', 'bottom', 'left']), - positionLeft: React.PropTypes.number, - positionTop: React.PropTypes.number, - arrowOffsetLeft: React.PropTypes.number, - arrowOffsetTop: React.PropTypes.number - }, - - getDefaultProps: function () { - return { - placement: 'right' - }; - }, - - render: function () { - var classes = {}; - classes['tooltip'] = true; - classes[this.props.placement] = true; - classes['in'] = this.props.positionLeft != null || this.props.positionTop != null; - - var style = {}; - style['left'] = this.props.positionLeft; - style['top'] = this.props.positionTop; - - var arrowStyle = {}; - arrowStyle['left'] = this.props.arrowOffsetLeft; - arrowStyle['top'] = this.props.arrowOffsetTop; - - return this.transferPropsTo( - React.DOM.div( {className:classSet(classes), style:style}, - React.DOM.div( {className:"tooltip-arrow", style:arrowStyle} ), - React.DOM.div( {className:"tooltip-inner"}, - this.props.children - ) - ) - ); - } -}); - -module.exports = Tooltip; -}); - -define('Well',['require','exports','module','react','./utils/classSet','./BootstrapMixin'],function (require, exports, module) {/** @jsx React.DOM */ - -var React = require('react'); -var classSet = require('./utils/classSet'); -var BootstrapMixin = require('./BootstrapMixin'); - -var Well = React.createClass({displayName: 'Well', - mixins: [BootstrapMixin], - - getDefaultProps: function () { - return { - bsClass: 'well' - }; - }, - - render: function () { - var classes = this.getBsClassSet(); - - return this.transferPropsTo( - React.DOM.div( {className:classSet(classes)}, - this.props.children - ) - ); - } -}); - -module.exports = Well; -}); - -/*global define */ - -define('react-bootstrap',['require','./Accordion','./Affix','./AffixMixin','./Alert','./BootstrapMixin','./Badge','./Button','./ButtonGroup','./ButtonToolbar','./Carousel','./CarouselItem','./Col','./CollapsableMixin','./DropdownButton','./DropdownMenu','./DropdownStateMixin','./FadeMixin','./Glyphicon','./Grid','./Input','./Interpolate','./Jumbotron','./Label','./ListGroup','./ListGroupItem','./MenuItem','./Modal','./Nav','./Navbar','./NavItem','./ModalTrigger','./OverlayTrigger','./OverlayMixin','./PageHeader','./Panel','./PanelGroup','./PageItem','./Pager','./Popover','./ProgressBar','./Row','./SplitButton','./SubNav','./TabbedArea','./Table','./TabPane','./Tooltip','./Well'],function (require) { - - - return { - Accordion: require('./Accordion'), - Affix: require('./Affix'), - AffixMixin: require('./AffixMixin'), - Alert: require('./Alert'), - BootstrapMixin: require('./BootstrapMixin'), - Badge: require('./Badge'), - Button: require('./Button'), - ButtonGroup: require('./ButtonGroup'), - ButtonToolbar: require('./ButtonToolbar'), - Carousel: require('./Carousel'), - CarouselItem: require('./CarouselItem'), - Col: require('./Col'), - CollapsableMixin: require('./CollapsableMixin'), - DropdownButton: require('./DropdownButton'), - DropdownMenu: require('./DropdownMenu'), - DropdownStateMixin: require('./DropdownStateMixin'), - FadeMixin: require('./FadeMixin'), - Glyphicon: require('./Glyphicon'), - Grid: require('./Grid'), - Input: require('./Input'), - Interpolate: require('./Interpolate'), - Jumbotron: require('./Jumbotron'), - Label: require('./Label'), - ListGroup: require('./ListGroup'), - ListGroupItem: require('./ListGroupItem'), - MenuItem: require('./MenuItem'), - Modal: require('./Modal'), - Nav: require('./Nav'), - Navbar: require('./Navbar'), - NavItem: require('./NavItem'), - ModalTrigger: require('./ModalTrigger'), - OverlayTrigger: require('./OverlayTrigger'), - OverlayMixin: require('./OverlayMixin'), - PageHeader: require('./PageHeader'), - Panel: require('./Panel'), - PanelGroup: require('./PanelGroup'), - PageItem: require('./PageItem'), - Pager: require('./Pager'), - Popover: require('./Popover'), - ProgressBar: require('./ProgressBar'), - Row: require('./Row'), - SplitButton: require('./SplitButton'), - SubNav: require('./SubNav'), - TabbedArea: require('./TabbedArea'), - Table: require('./Table'), - TabPane: require('./TabPane'), - Tooltip: require('./Tooltip'), - Well: require('./Well') - }; -}); - - //Register in the values from the outer closure for common dependencies - //as local almond modules - define('react', function () { - return React; - }); - - //Use almond's special top-level, synchronous require to trigger factory - //functions, get the final module value, and export it as the public - //value. - return require('react-bootstrap'); -})); diff --git a/web/src/vendor/react-router/react-router.js b/web/src/vendor/react-router/react-router.js index 942a2fc7..683ab14e 100644 --- a/web/src/vendor/react-router/react-router.js +++ b/web/src/vendor/react-router/react-router.js @@ -1,65 +1,76 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.ReactRouter=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ -var LocationDispatcher = _dereq_('../dispatchers/LocationDispatcher'); -var makePath = _dereq_('../utils/makePath'); - /** * Actions that modify the URL. */ var LocationActions = { - PUSH: 'push', - REPLACE: 'replace', - POP: 'pop', - UPDATE_SCROLL: 'update-scroll', - /** - * Transitions to the URL specified in the arguments by pushing - * a new URL onto the history stack. + * Indicates a new location is being pushed to the history stack. */ - transitionTo: function (to, params, query) { - LocationDispatcher.handleViewAction({ - type: LocationActions.PUSH, - path: makePath(to, params, query) - }); - }, + PUSH: 'push', /** - * Transitions to the URL specified in the arguments by replacing - * the current URL in the history stack. + * Indicates the current location should be replaced. */ - replaceWith: function (to, params, query) { - LocationDispatcher.handleViewAction({ - type: LocationActions.REPLACE, - path: makePath(to, params, query) - }); - }, + REPLACE: 'replace', /** - * Transitions to the previous URL. + * Indicates the most recent entry should be removed from the history stack. */ - goBack: function () { - LocationDispatcher.handleViewAction({ - type: LocationActions.POP - }); - }, + POP: 'pop' - /** - * Updates the window's scroll position to the last known position - * for the current URL path. - */ - updateScroll: function () { - LocationDispatcher.handleViewAction({ - type: LocationActions.UPDATE_SCROLL - }); +}; + +module.exports = LocationActions; + +},{}],2:[function(_dereq_,module,exports){ +var LocationActions = _dereq_('../actions/LocationActions'); + +/** + * A scroll behavior that attempts to imitate the default behavior + * of modern browsers. + */ +var ImitateBrowserBehavior = { + + updateScrollPosition: function (position, actionType) { + switch (actionType) { + case LocationActions.PUSH: + case LocationActions.REPLACE: + window.scrollTo(0, 0); + break; + case LocationActions.POP: + if (position) { + window.scrollTo(position.x, position.y); + } else { + window.scrollTo(0, 0); + } + break; + } } }; -module.exports = LocationActions; +module.exports = ImitateBrowserBehavior; + +},{"../actions/LocationActions":1}],3:[function(_dereq_,module,exports){ +/** + * A scroll behavior that always scrolls to the top of the page + * after a transition. + */ +var ScrollToTopBehavior = { + + updateScrollPosition: function () { + window.scrollTo(0, 0); + } -},{"../dispatchers/LocationDispatcher":8,"../utils/makePath":26}],2:[function(_dereq_,module,exports){ -var merge = _dereq_('react/lib/merge'); -var Route = _dereq_('./Route'); +}; + +module.exports = ScrollToTopBehavior; + +},{}],4:[function(_dereq_,module,exports){ +var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); +var FakeNode = _dereq_('../mixins/FakeNode'); +var PropTypes = _dereq_('../utils/PropTypes'); /** * A <DefaultRoute> component is a special kind of <Route> that @@ -67,25 +78,28 @@ var Route = _dereq_('./Route'); * Only one such route may be used at any given level in the * route hierarchy. */ -function DefaultRoute(props) { - return Route( - merge(props, { - path: null, - isDefault: true - }) - ); -} +var DefaultRoute = React.createClass({ + + displayName: 'DefaultRoute', + + mixins: [ FakeNode ], + + propTypes: { + name: React.PropTypes.string, + path: PropTypes.falsy, + handler: React.PropTypes.func.isRequired + } + +}); module.exports = DefaultRoute; -},{"./Route":6,"react/lib/merge":44}],3:[function(_dereq_,module,exports){ +},{"../mixins/FakeNode":14,"../utils/PropTypes":23}],5:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); -var ActiveState = _dereq_('../mixins/ActiveState'); -var transitionTo = _dereq_('../actions/LocationActions').transitionTo; -var withoutProperties = _dereq_('../utils/withoutProperties'); -var hasOwnProperty = _dereq_('../utils/hasOwnProperty'); -var makeHref = _dereq_('../utils/makeHref'); -var warning = _dereq_('react/lib/warning'); +var classSet = _dereq_('react/lib/cx'); +var assign = _dereq_('react/lib/Object.assign'); +var Navigation = _dereq_('../mixins/Navigation'); +var State = _dereq_('../mixins/State'); function isLeftClickEvent(event) { return event.button === 0; @@ -96,69 +110,32 @@ function isModifiedEvent(event) { } /** - * DEPRECATED: A map of <Link> component props that are reserved for use by the - * router and/or React. All other props are used as params that are - * interpolated into the link's path. - */ -var RESERVED_PROPS = { - to: true, - key: true, - className: true, - activeClassName: true, - query: true, - onClick:true, - children: true // ReactChildren -}; - -/** * <Link> components are used to create an <a> element that links to a route. * When that route is active, the link gets an "active" class name (or the * value of its `activeClassName` prop). * * For example, assuming you have the following route: * - * <Route name="showPost" path="/posts/:postId" handler={Post}/> + * <Route name="showPost" path="/posts/:postID" handler={Post}/> * * You could use the following component to link to that route: * - * <Link to="showPost" params={{postId: "123"}} /> + * <Link to="showPost" params={{ postID: "123" }} /> * * In addition to params, links may pass along query string parameters * using the `query` prop. * - * <Link to="showPost" params={{postId: "123"}} query={{show:true}}/> + * <Link to="showPost" params={{ postID: "123" }} query={{ show:true }}/> */ var Link = React.createClass({ displayName: 'Link', - mixins: [ ActiveState ], - - statics: { - - // TODO: Deprecate passing props as params in v1.0 - getUnreservedProps: function (props) { - var props = withoutProperties(props, RESERVED_PROPS); - warning( - Object.keys(props).length === 0, - 'Passing props for params on <Link>s is deprecated, '+ - 'please use the `params` property.' - ); - return props; - }, - - /** - * Returns a hash of URL parameters to use in this <Link>'s path. - */ - getParams: function (props) { - return props.params || Link.getUnreservedProps(props); - } - - }, + mixins: [ Navigation, State ], propTypes: { - to: React.PropTypes.string.isRequired, activeClassName: React.PropTypes.string.isRequired, + to: React.PropTypes.string.isRequired, params: React.PropTypes.object, query: React.PropTypes.object, onClick: React.PropTypes.func @@ -170,17 +147,30 @@ var Link = React.createClass({ }; }, - getInitialState: function () { - return { - isActive: false - }; + handleClick: function (event) { + var allowTransition = true; + var clickResult; + + if (this.props.onClick) + clickResult = this.props.onClick(event); + + if (isModifiedEvent(event) || !isLeftClickEvent(event)) + return; + + if (clickResult === false || event.defaultPrevented === true) + allowTransition = false; + + event.preventDefault(); + + if (allowTransition) + this.transitionTo(this.props.to, this.props.params, this.props.query); }, /** * Returns the value of the "href" attribute to use on the DOM element. */ getHref: function () { - return makeHref(this.props.to, Link.getParams(this.props), this.props.query); + return this.makeHref(this.props.to, this.props.params, this.props.query); }, /** @@ -188,59 +178,23 @@ var Link = React.createClass({ * the value of the activeClassName property when this <Link> is active. */ getClassName: function () { - var className = this.props.className || ''; - - if (this.state.isActive) - return className + ' ' + this.props.activeClassName; - - return className; - }, - - componentWillReceiveProps: function (nextProps) { - var params = Link.getParams(nextProps); - - this.setState({ - isActive: Link.isActive(nextProps.to, params, nextProps.query) - }); - }, - - updateActiveState: function () { - this.setState({ - isActive: Link.isActive(this.props.to, Link.getParams(this.props), this.props.query) - }); - }, - - handleClick: function (event) { - var allowTransition = true; - var ret; - - if (this.props.onClick) - ret = this.props.onClick(event); - - if (isModifiedEvent(event) || !isLeftClickEvent(event)) - return; + var classNames = {}; - if (ret === false || event.defaultPrevented === true) - allowTransition = false; + if (this.props.className) + classNames[this.props.className] = true; - event.preventDefault(); + if (this.isActive(this.props.to, this.props.params, this.props.query)) + classNames[this.props.activeClassName] = true; - if (allowTransition) - transitionTo(this.props.to, Link.getParams(this.props), this.props.query); + return classSet(classNames); }, render: function () { - var props = { + var props = assign({}, this.props, { href: this.getHref(), className: this.getClassName(), onClick: this.handleClick - }; - - // pull in props without overriding - for (var propName in this.props) { - if (hasOwnProperty(this.props, propName) && hasOwnProperty(props, propName) === false) - props[propName] = this.props[propName]; - } + }); return React.DOM.a(props, this.props.children); } @@ -249,9 +203,10 @@ var Link = React.createClass({ module.exports = Link; -},{"../actions/LocationActions":1,"../mixins/ActiveState":15,"../utils/hasOwnProperty":24,"../utils/makeHref":25,"../utils/withoutProperties":29,"react/lib/warning":48}],4:[function(_dereq_,module,exports){ -var merge = _dereq_('react/lib/merge'); -var Route = _dereq_('./Route'); +},{"../mixins/Navigation":15,"../mixins/State":18,"react/lib/Object.assign":38,"react/lib/cx":39}],6:[function(_dereq_,module,exports){ +var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); +var FakeNode = _dereq_('../mixins/FakeNode'); +var PropTypes = _dereq_('../utils/PropTypes'); /** * A <NotFoundRoute> is a special kind of <Route> that @@ -260,65 +215,51 @@ var Route = _dereq_('./Route'); * Only one such route may be used at any given level in the * route hierarchy. */ -function NotFoundRoute(props) { - return Route( - merge(props, { - path: null, - catchAll: true - }) - ); -} +var NotFoundRoute = React.createClass({ -module.exports = NotFoundRoute; + displayName: 'NotFoundRoute', -},{"./Route":6,"react/lib/merge":44}],5:[function(_dereq_,module,exports){ -var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); -var Route = _dereq_('./Route'); + mixins: [ FakeNode ], -function createRedirectHandler(to) { - return React.createClass({ - statics: { - willTransitionTo: function (transition, params, query) { - transition.redirect(to, params, query); - } - }, + propTypes: { + name: React.PropTypes.string, + path: PropTypes.falsy, + handler: React.PropTypes.func.isRequired + } - render: function () { - return null; - } - }); -} +}); + +module.exports = NotFoundRoute; + +},{"../mixins/FakeNode":14,"../utils/PropTypes":23}],7:[function(_dereq_,module,exports){ +var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); +var FakeNode = _dereq_('../mixins/FakeNode'); +var PropTypes = _dereq_('../utils/PropTypes'); /** * A <Redirect> component is a special kind of <Route> that always * redirects to another route when it matches. */ -function Redirect(props) { - return Route({ - name: props.name, - path: props.from || props.path || '*', - handler: createRedirectHandler(props.to) - }); -} +var Redirect = React.createClass({ + + displayName: 'Redirect', + + mixins: [ FakeNode ], + + propTypes: { + path: React.PropTypes.string, + from: React.PropTypes.string, // Alias for path. + to: React.PropTypes.string, + handler: PropTypes.falsy + } + +}); module.exports = Redirect; -},{"./Route":6}],6:[function(_dereq_,module,exports){ +},{"../mixins/FakeNode":14,"../utils/PropTypes":23}],8:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); -var withoutProperties = _dereq_('../utils/withoutProperties'); - -/** - * A map of <Route> component props that are reserved for use by the - * router and/or React. All other props are considered "static" and - * are passed through to the route handler. - */ -var RESERVED_PROPS = { - handler: true, - path: true, - defaultRoute: true, - paramNames: true, - children: true // ReactChildren -}; +var FakeNode = _dereq_('../mixins/FakeNode'); /** * <Route> components specify components that are rendered to the page when the @@ -330,40 +271,29 @@ var RESERVED_PROPS = { * "active" and their components are rendered into the DOM, nested in the same * order as they are in the tree. * - * Unlike Ember, a nested route's path does not build upon that of its parents. - * This may seem like it creates more work up front in specifying URLs, but it - * has the nice benefit of decoupling nested UI from "nested" URLs. - * * The preferred way to configure a router is using JSX. The XML-like syntax is * a great way to visualize how routes are laid out in an application. * - * React.renderComponent(( - * <Routes handler={App}> + * var routes = [ + * <Route handler={App}> * <Route name="login" handler={Login}/> * <Route name="logout" handler={Logout}/> * <Route name="about" handler={About}/> - * </Routes> - * ), document.body); - * - * If you don't use JSX, you can also assemble a Router programmatically using - * the standard React component JavaScript API. - * - * React.renderComponent(( - * Routes({ handler: App }, - * Route({ name: 'login', handler: Login }), - * Route({ name: 'logout', handler: Logout }), - * Route({ name: 'about', handler: About }) - * ) - * ), document.body); + * </Route> + * ]; + * + * Router.run(routes, function (Handler) { + * React.render(<Handler/>, document.body); + * }); * * Handlers for Route components that contain children can render their active - * child route using the activeRouteHandler prop. + * child route using a <RouteHandler> element. * * var App = React.createClass({ * render: function () { * return ( * <div class="application"> - * {this.props.activeRouteHandler()} + * <RouteHandler/> * </div> * ); * } @@ -373,542 +303,122 @@ var Route = React.createClass({ displayName: 'Route', - statics: { - - getUnreservedProps: function (props) { - return withoutProperties(props, RESERVED_PROPS); - }, - - }, + mixins: [ FakeNode ], propTypes: { - preserveScrollPosition: React.PropTypes.bool.isRequired, - handler: React.PropTypes.any.isRequired, + name: React.PropTypes.string, path: React.PropTypes.string, - name: React.PropTypes.string - }, - - getDefaultProps: function () { - return { - preserveScrollPosition: false - }; - }, - - render: function () { - throw new Error( - 'The <Route> component should not be rendered directly. You may be ' + - 'missing a <Routes> wrapper around your list of routes.' - ); + handler: React.PropTypes.func.isRequired, + ignoreScrollBehavior: React.PropTypes.bool } }); module.exports = Route; -},{"../utils/withoutProperties":29}],7:[function(_dereq_,module,exports){ +},{"../mixins/FakeNode":14}],9:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); -var warning = _dereq_('react/lib/warning'); -var copyProperties = _dereq_('react/lib/copyProperties'); -var Promise = _dereq_('when/lib/Promise'); -var LocationActions = _dereq_('../actions/LocationActions'); -var Route = _dereq_('../components/Route'); -var Path = _dereq_('../utils/Path'); -var Redirect = _dereq_('../utils/Redirect'); -var Transition = _dereq_('../utils/Transition'); -var DefaultLocation = _dereq_('../locations/DefaultLocation'); -var HashLocation = _dereq_('../locations/HashLocation'); -var HistoryLocation = _dereq_('../locations/HistoryLocation'); -var RefreshLocation = _dereq_('../locations/RefreshLocation'); -var ActiveStore = _dereq_('../stores/ActiveStore'); -var PathStore = _dereq_('../stores/PathStore'); -var RouteStore = _dereq_('../stores/RouteStore'); - -/** - * The ref name that can be used to reference the active route component. - */ -var REF_NAME = '__activeRoute__'; - -/** - * A hash of { name, location } pairs of all locations. - */ -var NAMED_LOCATIONS = { - hash: HashLocation, - history: HistoryLocation, - refresh: RefreshLocation -}; - -/** - * The default handler for aborted transitions. Redirects replace - * the current URL and all others roll it back. - */ -function defaultAbortedTransitionHandler(transition) { - var reason = transition.abortReason; - - if (reason instanceof Redirect) { - LocationActions.replaceWith(reason.to, reason.params, reason.query); - } else { - LocationActions.goBack(); - } -} /** - * The default handler for active state updates. + * A <RouteHandler> component renders the active child route handler + * when routes are nested. */ -function defaultActiveStateChangeHandler(state) { - ActiveStore.updateState(state); -} - -/** - * The default handler for errors that were thrown asynchronously - * while transitioning. The default behavior is to re-throw the - * error so that it isn't silently swallowed. - */ -function defaultTransitionErrorHandler(error) { - throw error; // This error probably originated in a transition hook. -} +var RouteHandler = React.createClass({ -function maybeUpdateScroll(routes, rootRoute) { - if (!routes.props.preserveScrollPosition && !rootRoute.props.preserveScrollPosition) - LocationActions.updateScroll(); -} - -/** - * The <Routes> component configures the route hierarchy and renders the - * route matching the current location when rendered into a document. - * - * See the <Route> component for more details. - */ -var Routes = React.createClass({ - - displayName: 'Routes', - - propTypes: { - onAbortedTransition: React.PropTypes.func.isRequired, - onActiveStateChange: React.PropTypes.func.isRequired, - onTransitionError: React.PropTypes.func.isRequired, - preserveScrollPosition: React.PropTypes.bool, - location: function (props, propName, componentName) { - var location = props[propName]; - - if (typeof location === 'string' && !(location in NAMED_LOCATIONS)) - return new Error('Unknown location "' + location + '", see ' + componentName); - } - }, + displayName: 'RouteHandler', getDefaultProps: function () { return { - onAbortedTransition: defaultAbortedTransitionHandler, - onActiveStateChange: defaultActiveStateChangeHandler, - onTransitionError: defaultTransitionErrorHandler, - preserveScrollPosition: false, - location: DefaultLocation + ref: '__routeHandler__' }; }, - getInitialState: function () { - return { - routes: RouteStore.registerChildren(this.props.children, this) - }; + contextTypes: { + getRouteAtDepth: React.PropTypes.func.isRequired, + getRouteComponents: React.PropTypes.func.isRequired, + routeHandlers: React.PropTypes.array.isRequired }, - getLocation: function () { - var location = this.props.location; - - if (typeof location === 'string') - return NAMED_LOCATIONS[location]; - - return location; + childContextTypes: { + routeHandlers: React.PropTypes.array.isRequired }, - componentWillMount: function () { - PathStore.setup(this.getLocation()); - PathStore.addChangeListener(this.handlePathChange); + getChildContext: function () { + return { + routeHandlers: this.context.routeHandlers.concat([ this ]) + }; }, - componentDidMount: function () { - this.handlePathChange(); + getRouteDepth: function () { + return this.context.routeHandlers.length - 1; }, - componentWillUnmount: function () { - PathStore.removeChangeListener(this.handlePathChange); + componentDidMount: function () { + this._updateRouteComponent(); }, - handlePathChange: function () { - this.dispatch(PathStore.getCurrentPath()); + componentDidUpdate: function () { + this._updateRouteComponent(); }, - /** - * Performs a depth-first search for the first route in the tree that matches - * on the given path. Returns an array of all routes in the tree leading to - * the one that matched in the format { route, params } where params is an - * object that contains the URL parameters relevant to that route. Returns - * null if no route in the tree matches the path. - * - * React.renderComponent( - * <Routes> - * <Route handler={App}> - * <Route name="posts" handler={Posts}/> - * <Route name="post" path="/posts/:id" handler={Post}/> - * </Route> - * </Routes> - * ).match('/posts/123'); => [ { route: <AppRoute>, params: {} }, - * { route: <PostRoute>, params: { id: '123' } } ] - */ - match: function (path) { - return findMatches(Path.withoutQuery(path), this.state.routes, this.props.defaultRoute, this.props.notFoundRoute); - }, - - /** - * Performs a transition to the given path and returns a promise for the - * Transition object that was used. - * - * In order to do this, the router first determines which routes are involved - * in the transition beginning with the current route, up the route tree to - * the first parent route that is shared with the destination route, and back - * down the tree to the destination route. The willTransitionFrom static - * method is invoked on all route handlers we're transitioning away from, in - * reverse nesting order. Likewise, the willTransitionTo static method - * is invoked on all route handlers we're transitioning to. - * - * Both willTransitionFrom and willTransitionTo hooks may either abort or - * redirect the transition. If they need to resolve asynchronously, they may - * return a promise. - * - * Any error that occurs asynchronously during the transition is re-thrown in - * the top-level scope unless returnRejectedPromise is true, in which case a - * rejected promise is returned so the caller may handle the error. - * - * Note: This function does not update the URL in a browser's location bar. - * If you want to keep the URL in sync with transitions, use Router.transitionTo, - * Router.replaceWith, or Router.goBack instead. - */ - dispatch: function (path, returnRejectedPromise) { - var transition = new Transition(path); - var routes = this; - - var promise = runTransitionHooks(routes, transition).then(function (nextState) { - if (transition.isAborted) { - routes.props.onAbortedTransition(transition); - } else if (nextState) { - routes.setState(nextState); - routes.props.onActiveStateChange(nextState); - - // TODO: add functional test - var rootMatch = getRootMatch(nextState.matches); - - if (rootMatch) - maybeUpdateScroll(routes, rootMatch.route); - } - - return transition; - }); - - if (!returnRejectedPromise) { - promise = promise.then(undefined, function (error) { - // Use setTimeout to break the promise chain. - setTimeout(function () { - routes.props.onTransitionError(error); - }); - }); - } - - return promise; + _updateRouteComponent: function () { + var depth = this.getRouteDepth(); + var components = this.context.getRouteComponents(); + components[depth] = this.refs[this.props.ref]; }, render: function () { - if (!this.state.path) - return null; - - var matches = this.state.matches; - if (matches.length) { - // matches[0] corresponds to the top-most match - return matches[0].route.props.handler(computeHandlerProps(matches, this.state.activeQuery)); - } else { - return null; - } - } - -}); - -function findMatches(path, routes, defaultRoute, notFoundRoute) { - var matches = null, route, params; - - for (var i = 0, len = routes.length; i < len; ++i) { - route = routes[i]; - - // Check the subtree first to find the most deeply-nested match. - matches = findMatches(path, route.props.children, route.props.defaultRoute, route.props.notFoundRoute); - - if (matches != null) { - var rootParams = getRootMatch(matches).params; - - params = route.props.paramNames.reduce(function (params, paramName) { - params[paramName] = rootParams[paramName]; - return params; - }, {}); - - matches.unshift(makeMatch(route, params)); - - return matches; - } - - // No routes in the subtree matched, so check this route. - params = Path.extractParams(route.props.path, path); - - if (params) - return [ makeMatch(route, params) ]; - } - - // No routes matched, so try the default route if there is one. - if (defaultRoute && (params = Path.extractParams(defaultRoute.props.path, path))) - return [ makeMatch(defaultRoute, params) ]; - - // Last attempt: does the "not found" route match? - if (notFoundRoute && (params = Path.extractParams(notFoundRoute.props.path, path))) - return [ makeMatch(notFoundRoute, params) ]; - - return matches; -} - -function makeMatch(route, params) { - return { route: route, params: params }; -} - -function hasMatch(matches, match) { - return matches.some(function (m) { - if (m.route !== match.route) - return false; - - for (var property in m.params) { - if (m.params[property] !== match.params[property]) - return false; - } - - return true; - }); -} - -function getRootMatch(matches) { - return matches[matches.length - 1]; -} - -function updateMatchComponents(matches, refs) { - var i = 0, component; - while (component = refs[REF_NAME]) { - matches[i++].component = component; - refs = component.refs; - } -} - -/** - * Runs all transition hooks that are required to get from the current state - * to the state specified by the given transition and updates the current state - * if they all pass successfully. Returns a promise that resolves to the new - * state if it needs to be updated, or undefined if not. - */ -function runTransitionHooks(routes, transition) { - if (routes.state.path === transition.path) - return Promise.resolve(); // Nothing to do! - - var currentMatches = routes.state.matches; - var nextMatches = routes.match(transition.path); - - warning( - nextMatches, - 'No route matches path "' + transition.path + '". Make sure you have ' + - '<Route path="' + transition.path + '"> somewhere in your routes' - ); - - if (!nextMatches) - nextMatches = []; - - var fromMatches, toMatches; - if (currentMatches) { - updateMatchComponents(currentMatches, routes.refs); - - fromMatches = currentMatches.filter(function (match) { - return !hasMatch(nextMatches, match); - }); - - toMatches = nextMatches.filter(function (match) { - return !hasMatch(currentMatches, match); - }); - } else { - fromMatches = []; - toMatches = nextMatches; - } - - var query = Path.extractQuery(transition.path) || {}; - - return runTransitionFromHooks(fromMatches, transition).then(function () { - if (transition.isAborted) - return; // No need to continue. - - return runTransitionToHooks(toMatches, transition, query).then(function () { - if (transition.isAborted) - return; // No need to continue. - - var rootMatch = getRootMatch(nextMatches); - var params = (rootMatch && rootMatch.params) || {}; - - return { - path: transition.path, - matches: nextMatches, - activeParams: params, - activeQuery: query, - activeRoutes: nextMatches.map(function (match) { - return match.route; - }) - }; - }); - }); -} - -/** - * Calls the willTransitionFrom hook of all handlers in the given matches - * serially in reverse with the transition object and the current instance of - * the route's handler, so that the deepest nested handlers are called first. - * Returns a promise that resolves after the last handler. - */ -function runTransitionFromHooks(matches, transition) { - var promise = Promise.resolve(); - - reversedArray(matches).forEach(function (match) { - promise = promise.then(function () { - var handler = match.route.props.handler; - - if (!transition.isAborted && handler.willTransitionFrom) - return handler.willTransitionFrom(transition, match.component); - }); - }); - - return promise; -} - -/** - * Calls the willTransitionTo hook of all handlers in the given matches serially - * with the transition object and any params that apply to that handler. Returns - * a promise that resolves after the last handler. - */ -function runTransitionToHooks(matches, transition, query) { - var promise = Promise.resolve(); - - matches.forEach(function (match) { - promise = promise.then(function () { - var handler = match.route.props.handler; - - if (!transition.isAborted && handler.willTransitionTo) - return handler.willTransitionTo(transition, match.params, query); - }); - }); - - return promise; -} - -/** - * Given an array of matches as returned by findMatches, return a descriptor for - * the handler hierarchy specified by the route. - */ -function computeHandlerProps(matches, query) { - var props = { - ref: null, - key: null, - params: null, - query: null, - activeRouteHandler: returnNull - }; - - var childHandler; - reversedArray(matches).forEach(function (match) { - var route = match.route; - - props = Route.getUnreservedProps(route.props); - - props.ref = REF_NAME; - props.params = match.params; - props.query = query; - - if (route.props.addHandlerKey) - props.key = Path.injectParams(route.props.path, match.params); - - if (childHandler) { - props.activeRouteHandler = childHandler; - } else { - props.activeRouteHandler = returnNull; - } - - childHandler = function (props, addedProps) { - if (arguments.length > 2 && typeof arguments[2] !== 'undefined') - throw new Error('Passing children to a route handler is not supported'); - - return route.props.handler(copyProperties(props, addedProps)); - }.bind(this, props); - }); - - return props; -} - -function returnNull() { - return null; -} - -function reversedArray(array) { - return array.slice(0).reverse(); -} - -module.exports = Routes; - -},{"../actions/LocationActions":1,"../components/Route":6,"../locations/DefaultLocation":10,"../locations/HashLocation":11,"../locations/HistoryLocation":12,"../locations/RefreshLocation":14,"../stores/ActiveStore":17,"../stores/PathStore":18,"../stores/RouteStore":19,"../utils/Path":20,"../utils/Redirect":21,"../utils/Transition":22,"react/lib/copyProperties":40,"react/lib/warning":48,"when/lib/Promise":49}],8:[function(_dereq_,module,exports){ -var copyProperties = _dereq_('react/lib/copyProperties'); -var Dispatcher = _dereq_('flux').Dispatcher; - -/** - * Dispatches actions that modify the URL. - */ -var LocationDispatcher = copyProperties(new Dispatcher, { - - handleViewAction: function (action) { - this.dispatch({ - source: 'VIEW_ACTION', - action: action - }); + var route = this.context.getRouteAtDepth(this.getRouteDepth()); + return route ? React.createElement(route.handler, this.props) : null; } }); -module.exports = LocationDispatcher; - -},{"flux":31,"react/lib/copyProperties":40}],9:[function(_dereq_,module,exports){ -exports.goBack = _dereq_('./actions/LocationActions').goBack; -exports.replaceWith = _dereq_('./actions/LocationActions').replaceWith; -exports.transitionTo = _dereq_('./actions/LocationActions').transitionTo; +module.exports = RouteHandler; +},{}],10:[function(_dereq_,module,exports){ exports.DefaultRoute = _dereq_('./components/DefaultRoute'); exports.Link = _dereq_('./components/Link'); exports.NotFoundRoute = _dereq_('./components/NotFoundRoute'); exports.Redirect = _dereq_('./components/Redirect'); exports.Route = _dereq_('./components/Route'); -exports.Routes = _dereq_('./components/Routes'); +exports.RouteHandler = _dereq_('./components/RouteHandler'); -exports.ActiveState = _dereq_('./mixins/ActiveState'); -exports.AsyncState = _dereq_('./mixins/AsyncState'); +exports.HashLocation = _dereq_('./locations/HashLocation'); +exports.HistoryLocation = _dereq_('./locations/HistoryLocation'); +exports.RefreshLocation = _dereq_('./locations/RefreshLocation'); -exports.makeHref = _dereq_('./utils/makeHref'); +exports.ImitateBrowserBehavior = _dereq_('./behaviors/ImitateBrowserBehavior'); +exports.ScrollToTopBehavior = _dereq_('./behaviors/ScrollToTopBehavior'); -},{"./actions/LocationActions":1,"./components/DefaultRoute":2,"./components/Link":3,"./components/NotFoundRoute":4,"./components/Redirect":5,"./components/Route":6,"./components/Routes":7,"./mixins/ActiveState":15,"./mixins/AsyncState":16,"./utils/makeHref":25}],10:[function(_dereq_,module,exports){ -module.exports = "production" === 'test' - ? _dereq_('./MemoryLocation') - : _dereq_('./HashLocation'); +exports.Navigation = _dereq_('./mixins/Navigation'); +exports.State = _dereq_('./mixins/State'); -},{"./HashLocation":11,"./MemoryLocation":13}],11:[function(_dereq_,module,exports){ +exports.create = _dereq_('./utils/createRouter'); +exports.run = _dereq_('./utils/runRouter'); + +},{"./behaviors/ImitateBrowserBehavior":2,"./behaviors/ScrollToTopBehavior":3,"./components/DefaultRoute":4,"./components/Link":5,"./components/NotFoundRoute":6,"./components/Redirect":7,"./components/Route":8,"./components/RouteHandler":9,"./locations/HashLocation":11,"./locations/HistoryLocation":12,"./locations/RefreshLocation":13,"./mixins/Navigation":15,"./mixins/State":18,"./utils/createRouter":26,"./utils/runRouter":30}],11:[function(_dereq_,module,exports){ var invariant = _dereq_('react/lib/invariant'); -var ExecutionEnvironment = _dereq_('react/lib/ExecutionEnvironment'); -var getWindowPath = _dereq_('../utils/getWindowPath'); +var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM; +var LocationActions = _dereq_('../actions/LocationActions'); +var Path = _dereq_('../utils/Path'); +/** + * Returns the current URL path from `window.location.hash`, including query string + */ function getHashPath() { - return window.location.hash.substr(1); + invariant( + canUseDOM, + 'getHashPath needs a DOM' + ); + + return Path.decode( + window.location.hash.substr(1) + ); } +var _actionType; + function ensureSlash() { var path = getHashPath(); @@ -920,11 +430,30 @@ function ensureSlash() { return false; } -var _onChange; +var _changeListeners = []; + +function notifyChange(type) { + var change = { + path: getHashPath(), + type: type + }; -function handleHashChange() { - if (ensureSlash()) - _onChange(); + _changeListeners.forEach(function (listener) { + listener(change); + }); +} + +var _isListening = false; + +function onHashChange() { + if (ensureSlash()) { + // If we don't have an _actionType then all we know is the hash + // changed. It was probably caused by the user clicking the Back + // button, but may have also been the Forward button or manual + // manipulation. So just guess 'pop'. + notifyChange(_actionType || LocationActions.POP); + _actionType = null; + } } /** @@ -932,40 +461,36 @@ function handleHashChange() { */ var HashLocation = { - setup: function (onChange) { - invariant( - ExecutionEnvironment.canUseDOM, - 'You cannot use HashLocation in an environment with no DOM' - ); - - _onChange = onChange; + addChangeListener: function (listener) { + _changeListeners.push(listener); + // Do this BEFORE listening for hashchange. ensureSlash(); + if (_isListening) + return; + if (window.addEventListener) { - window.addEventListener('hashchange', handleHashChange, false); + window.addEventListener('hashchange', onHashChange, false); } else { - window.attachEvent('onhashchange', handleHashChange); + window.attachEvent('onhashchange', onHashChange); } - }, - teardown: function () { - if (window.removeEventListener) { - window.removeEventListener('hashchange', handleHashChange, false); - } else { - window.detachEvent('onhashchange', handleHashChange); - } + _isListening = true; }, push: function (path) { - window.location.hash = path; + _actionType = LocationActions.PUSH; + window.location.hash = Path.encode(path); }, replace: function (path) { - window.location.replace(getWindowPath() + '#' + path); + _actionType = LocationActions.REPLACE; + window.location.replace(window.location.pathname + '#' + Path.encode(path)); }, pop: function () { + _actionType = LocationActions.POP; window.history.back(); }, @@ -979,49 +504,73 @@ var HashLocation = { module.exports = HashLocation; -},{"../utils/getWindowPath":23,"react/lib/ExecutionEnvironment":39,"react/lib/invariant":42}],12:[function(_dereq_,module,exports){ +},{"../actions/LocationActions":1,"../utils/Path":21,"react/lib/ExecutionEnvironment":37,"react/lib/invariant":41}],12:[function(_dereq_,module,exports){ var invariant = _dereq_('react/lib/invariant'); -var ExecutionEnvironment = _dereq_('react/lib/ExecutionEnvironment'); -var getWindowPath = _dereq_('../utils/getWindowPath'); +var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM; +var LocationActions = _dereq_('../actions/LocationActions'); +var Path = _dereq_('../utils/Path'); + +/** + * Returns the current URL path from `window.location`, including query string + */ +function getWindowPath() { + invariant( + canUseDOM, + 'getWindowPath needs a DOM' + ); + + return Path.decode( + window.location.pathname + window.location.search + ); +} + +var _changeListeners = []; + +function notifyChange(type) { + var change = { + path: getWindowPath(), + type: type + }; + + _changeListeners.forEach(function (listener) { + listener(change); + }); +} -var _onChange; +var _isListening = false; + +function onPopState() { + notifyChange(LocationActions.POP); +} /** * A Location that uses HTML5 history. */ var HistoryLocation = { - setup: function (onChange) { - invariant( - ExecutionEnvironment.canUseDOM, - 'You cannot use HistoryLocation in an environment with no DOM' - ); + addChangeListener: function (listener) { + _changeListeners.push(listener); - _onChange = onChange; + if (_isListening) + return; if (window.addEventListener) { - window.addEventListener('popstate', _onChange, false); + window.addEventListener('popstate', onPopState, false); } else { - window.attachEvent('popstate', _onChange); + window.attachEvent('popstate', onPopState); } - }, - teardown: function () { - if (window.removeEventListener) { - window.removeEventListener('popstate', _onChange, false); - } else { - window.detachEvent('popstate', _onChange); - } + _isListening = true; }, push: function (path) { - window.history.pushState({ path: path }, '', path); - _onChange(); + window.history.pushState({ path: path }, '', Path.encode(path)); + notifyChange(LocationActions.PUSH); }, replace: function (path) { - window.history.replaceState({ path: path }, '', path); - _onChange(); + window.history.replaceState({ path: path }, '', Path.encode(path)); + notifyChange(LocationActions.REPLACE); }, pop: function () { @@ -1038,670 +587,444 @@ var HistoryLocation = { module.exports = HistoryLocation; -},{"../utils/getWindowPath":23,"react/lib/ExecutionEnvironment":39,"react/lib/invariant":42}],13:[function(_dereq_,module,exports){ -var warning = _dereq_('react/lib/warning'); - -var _lastPath = null; -var _currentPath = null; -var _onChange; +},{"../actions/LocationActions":1,"../utils/Path":21,"react/lib/ExecutionEnvironment":37,"react/lib/invariant":41}],13:[function(_dereq_,module,exports){ +var HistoryLocation = _dereq_('./HistoryLocation'); +var Path = _dereq_('../utils/Path'); /** - * A Location that does not require a DOM. + * A Location that uses full page refreshes. This is used as + * the fallback for HistoryLocation in browsers that do not + * support the HTML5 history API. */ -var MemoryLocation = { - - setup: function (onChange) { - _onChange = onChange; - }, +var RefreshLocation = { push: function (path) { - _lastPath = _currentPath; - _currentPath = path; - _onChange(); + window.location = Path.encode(path); }, replace: function (path) { - _currentPath = path; - _onChange(); + window.location.replace(Path.encode(path)); }, pop: function () { - warning( - _lastPath != null, - 'You cannot use MemoryLocation to go back more than once' - ); - - _currentPath = _lastPath; - _lastPath = null; - _onChange(); + window.history.back(); }, - getCurrentPath: function () { - return _currentPath || '/'; - }, + getCurrentPath: HistoryLocation.getCurrentPath, toString: function () { - return '<MemoryLocation>'; + return '<RefreshLocation>'; } }; -module.exports = MemoryLocation; +module.exports = RefreshLocation; -},{"react/lib/warning":48}],14:[function(_dereq_,module,exports){ +},{"../utils/Path":21,"./HistoryLocation":12}],14:[function(_dereq_,module,exports){ var invariant = _dereq_('react/lib/invariant'); -var ExecutionEnvironment = _dereq_('react/lib/ExecutionEnvironment'); -var getWindowPath = _dereq_('../utils/getWindowPath'); -/** - * A Location that uses full page refreshes. This is used as - * the fallback for HistoryLocation in browsers that do not - * support the HTML5 history API. - */ -var RefreshLocation = { +var FakeNode = { - setup: function () { + render: function () { invariant( - ExecutionEnvironment.canUseDOM, - 'You cannot use RefreshLocation in an environment with no DOM' + false, + '%s elements should not be rendered', + this.constructor.displayName ); - }, - - push: function (path) { - window.location = path; - }, - - replace: function (path) { - window.location.replace(path); - }, - - pop: function () { - window.history.back(); - }, - - getCurrentPath: getWindowPath, - - toString: function () { - return '<RefreshLocation>'; } }; -module.exports = RefreshLocation; +module.exports = FakeNode; -},{"../utils/getWindowPath":23,"react/lib/ExecutionEnvironment":39,"react/lib/invariant":42}],15:[function(_dereq_,module,exports){ -var ActiveStore = _dereq_('../stores/ActiveStore'); +},{"react/lib/invariant":41}],15:[function(_dereq_,module,exports){ +var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); /** - * A mixin for components that need to know about the routes, params, - * and query that are currently active. Components that use it get two - * things: - * - * 1. An `isActive` static method they can use to check if a route, - * params, and query are active. - * 2. An `updateActiveState` instance method that is called when the - * active state changes. + * A mixin for components that modify the URL. * * Example: * - * var Tab = React.createClass({ - * - * mixins: [ Router.ActiveState ], - * - * getInitialState: function () { - * return { - * isActive: false - * }; + * var MyLink = React.createClass({ + * mixins: [ Router.Navigation ], + * handleClick: function (event) { + * event.preventDefault(); + * this.transitionTo('aRoute', { the: 'params' }, { the: 'query' }); * }, - * - * updateActiveState: function () { - * this.setState({ - * isActive: Tab.isActive(routeName, params, query) - * }) + * render: function () { + * return ( + * <a onClick={this.handleClick}>Click me!</a> + * ); * } - * * }); */ -var ActiveState = { - - statics: { +var Navigation = { - /** - * Returns true if the route with the given name, URL parameters, and query - * are all currently active. - */ - isActive: ActiveStore.isActive + contextTypes: { + makePath: React.PropTypes.func.isRequired, + makeHref: React.PropTypes.func.isRequired, + transitionTo: React.PropTypes.func.isRequired, + replaceWith: React.PropTypes.func.isRequired, + goBack: React.PropTypes.func.isRequired + }, + /** + * Returns an absolute URL path created from the given route + * name, URL parameters, and query values. + */ + makePath: function (to, params, query) { + return this.context.makePath(to, params, query); }, - componentWillMount: function () { - ActiveStore.addChangeListener(this.handleActiveStateChange); + /** + * Returns a string that may safely be used as the href of a + * link to the route with the given name. + */ + makeHref: function (to, params, query) { + return this.context.makeHref(to, params, query); }, - componentDidMount: function () { - if (this.updateActiveState) - this.updateActiveState(); + /** + * Transitions to the URL specified in the arguments by pushing + * a new URL onto the history stack. + */ + transitionTo: function (to, params, query) { + this.context.transitionTo(to, params, query); }, - componentWillUnmount: function () { - ActiveStore.removeChangeListener(this.handleActiveStateChange); + /** + * Transitions to the URL specified in the arguments by replacing + * the current URL in the history stack. + */ + replaceWith: function (to, params, query) { + this.context.replaceWith(to, params, query); }, - handleActiveStateChange: function () { - if (this.isMounted() && typeof this.updateActiveState === 'function') - this.updateActiveState(); + /** + * Transitions to the previous URL. + */ + goBack: function () { + this.context.goBack(); } }; -module.exports = ActiveState; +module.exports = Navigation; -},{"../stores/ActiveStore":17}],16:[function(_dereq_,module,exports){ +},{}],16:[function(_dereq_,module,exports){ var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); -var resolveAsyncState = _dereq_('../utils/resolveAsyncState'); /** - * A mixin for route handler component classes that fetch at least - * part of their state asynchronously. Classes that use it should - * declare a static `getInitialAsyncState` method that fetches state - * for a component after it mounts. This function is given three - * arguments: 1) the current route params, 2) the current query and - * 3) a function that can be used to set state as it is received. - * - * Much like the familiar `getInitialState` method, `getInitialAsyncState` - * should return a hash of key/value pairs to use in the component's - * state. The difference is that the values may be promises. As these - * values resolve, the component's state is updated. You should only - * ever need to use the setState function for doing things like - * streaming data and/or updating progress. - * - * Example: - * - * var User = React.createClass({ - * - * statics: { - * - * getInitialAsyncState: function (params, query, setState) { - * // Return a hash with keys named after the state variables - * // you want to set, as you normally do in getInitialState, - * // except the values may be immediate values or promises. - * // The state is automatically updated as promises resolve. - * return { - * user: getUserByID(params.userID) // may be a promise - * }; - * - * // Or, use the setState function to stream data! - * var buffer = ''; - * - * return { - * - * // Same as above, the stream state variable is set to the - * // value returned by this promise when it resolves. - * stream: getStreamingData(params.userID, function (chunk) { - * buffer += chunk; - * - * // Notify of progress. - * setState({ - * streamBuffer: buffer - * }); - * }) - * - * }; - * } - * - * }, - * - * getInitialState: function () { - * return { - * user: null, // Receives a value when getUserByID resolves. - * stream: null, // Receives a value when getStreamingData resolves. - * streamBuffer: '' // Used to track data as it loads. - * }; - * }, - * - * render: function () { - * if (!this.state.user) - * return <LoadingUser/>; - * - * return ( - * <div> - * <p>Welcome {this.state.user.name}!</p> - * <p>So far, you've received {this.state.streamBuffer.length} data!</p> - * </div> - * ); - * } - * - * }); - * - * When testing, use the `initialAsyncState` prop to simulate asynchronous - * data fetching. When this prop is present, no attempt is made to retrieve - * additional state via `getInitialAsyncState`. + * Provides the router with context for Router.Navigation. */ -var AsyncState = { - - propTypes: { - initialAsyncState: React.PropTypes.object - }, +var NavigationContext = { - getInitialState: function () { - return this.props.initialAsyncState || null; + childContextTypes: { + makePath: React.PropTypes.func.isRequired, + makeHref: React.PropTypes.func.isRequired, + transitionTo: React.PropTypes.func.isRequired, + replaceWith: React.PropTypes.func.isRequired, + goBack: React.PropTypes.func.isRequired }, - updateAsyncState: function (state) { - if (this.isMounted()) - this.setState(state); - }, - - componentDidMount: function () { - if (this.props.initialAsyncState || typeof this.constructor.getInitialAsyncState !== 'function') - return; - - resolveAsyncState( - this.constructor.getInitialAsyncState(this.props.params, this.props.query, this.updateAsyncState), - this.updateAsyncState - ); + getChildContext: function () { + return { + makePath: this.constructor.makePath, + makeHref: this.constructor.makeHref, + transitionTo: this.constructor.transitionTo, + replaceWith: this.constructor.replaceWith, + goBack: this.constructor.goBack + }; } }; -module.exports = AsyncState; +module.exports = NavigationContext; -},{"../utils/resolveAsyncState":27}],17:[function(_dereq_,module,exports){ -var EventEmitter = _dereq_('events').EventEmitter; +},{}],17:[function(_dereq_,module,exports){ +var invariant = _dereq_('react/lib/invariant'); +var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM; +var getWindowScrollPosition = _dereq_('../utils/getWindowScrollPosition'); -var CHANGE_EVENT = 'change'; -var _events = new EventEmitter; +function shouldUpdateScroll(state, prevState) { + if (!prevState) + return true; -_events.setMaxListeners(0); + // Don't update scroll position when only the query has changed. + if (state.pathname === prevState.pathname) + return false; -function notifyChange() { - _events.emit(CHANGE_EVENT); -} + var routes = state.routes; + var prevRoutes = prevState.routes; -var _activeRoutes = []; -var _activeParams = {}; -var _activeQuery = {}; + var sharedAncestorRoutes = routes.filter(function (route) { + return prevRoutes.indexOf(route) !== -1; + }); -function routeIsActive(routeName) { - return _activeRoutes.some(function (route) { - return route.props.name === routeName; + return !sharedAncestorRoutes.some(function (route) { + return route.ignoreScrollBehavior; }); } -function paramsAreActive(params) { - for (var property in params) { - if (_activeParams[property] !== String(params[property])) - return false; - } - - return true; -} +/** + * Provides the router with the ability to manage window scroll position + * according to its scroll behavior. + */ +var Scrolling = { -function queryIsActive(query) { - for (var property in query) { - if (_activeQuery[property] !== String(query[property])) - return false; - } + statics: { + /** + * Records curent scroll position as the last known position for the given URL path. + */ + recordScrollPosition: function (path) { + if (!this.scrollHistory) + this.scrollHistory = {}; - return true; -} + this.scrollHistory[path] = getWindowScrollPosition(); + }, -/** - * The ActiveStore keeps track of which routes, URL and query parameters are - * currently active on a page. <Link>s subscribe to the ActiveStore to know - * whether or not they are active. - */ -var ActiveStore = { + /** + * Returns the last known scroll position for the given URL path. + */ + getScrollPosition: function (path) { + if (!this.scrollHistory) + this.scrollHistory = {}; - addChangeListener: function (listener) { - _events.on(CHANGE_EVENT, listener); + return this.scrollHistory[path] || null; + } }, - removeChangeListener: function (listener) { - _events.removeListener(CHANGE_EVENT, listener); + componentWillMount: function () { + invariant( + this.getScrollBehavior() == null || canUseDOM, + 'Cannot use scroll behavior without a DOM' + ); }, - /** - * Updates the currently active state and notifies all listeners. - * This is automatically called by routes as they become active. - */ - updateState: function (state) { - state = state || {}; - - _activeRoutes = state.activeRoutes || []; - _activeParams = state.activeParams || {}; - _activeQuery = state.activeQuery || {}; + componentDidMount: function () { + this._updateScroll(); + }, - notifyChange(); + componentDidUpdate: function (prevProps, prevState) { + this._updateScroll(prevState); }, - /** - * Returns true if the route with the given name, URL parameters, and query - * are all currently active. - */ - isActive: function (routeName, params, query) { - var isActive = routeIsActive(routeName) && paramsAreActive(params); + _updateScroll: function (prevState) { + if (!shouldUpdateScroll(this.state, prevState)) + return; - if (query) - return isActive && queryIsActive(query); + var scrollBehavior = this.getScrollBehavior(); - return isActive; + if (scrollBehavior) + scrollBehavior.updateScrollPosition( + this.constructor.getScrollPosition(this.state.path), + this.state.action + ); } }; -module.exports = ActiveStore; +module.exports = Scrolling; -},{"events":30}],18:[function(_dereq_,module,exports){ -var warning = _dereq_('react/lib/warning'); -var EventEmitter = _dereq_('events').EventEmitter; -var LocationActions = _dereq_('../actions/LocationActions'); -var LocationDispatcher = _dereq_('../dispatchers/LocationDispatcher'); -var supportsHistory = _dereq_('../utils/supportsHistory'); -var HistoryLocation = _dereq_('../locations/HistoryLocation'); -var RefreshLocation = _dereq_('../locations/RefreshLocation'); - -var CHANGE_EVENT = 'change'; -var _events = new EventEmitter; - -function notifyChange() { - _events.emit(CHANGE_EVENT); -} - -var _scrollPositions = {}; - -function recordScrollPosition(path) { - _scrollPositions[path] = { - x: window.scrollX, - y: window.scrollY - }; -} - -function updateScrollPosition(path) { - var p = PathStore.getScrollPosition(path); - window.scrollTo(p.x, p.y); -} - -var _location; +},{"../utils/getWindowScrollPosition":28,"react/lib/ExecutionEnvironment":37,"react/lib/invariant":41}],18:[function(_dereq_,module,exports){ +var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); /** - * The PathStore keeps track of the current URL path and manages - * the location strategy that is used to update the URL. + * A mixin for components that need to know the path, routes, URL + * params and query that are currently active. + * + * Example: + * + * var AboutLink = React.createClass({ + * mixins: [ Router.State ], + * render: function () { + * var className = this.props.className; + * + * if (this.isActive('about')) + * className += ' is-active'; + * + * return React.DOM.a({ className: className }, this.props.children); + * } + * }); */ -var PathStore = { +var State = { - addChangeListener: function (listener) { - _events.on(CHANGE_EVENT, listener); + contextTypes: { + getCurrentPath: React.PropTypes.func.isRequired, + getCurrentRoutes: React.PropTypes.func.isRequired, + getCurrentPathname: React.PropTypes.func.isRequired, + getCurrentParams: React.PropTypes.func.isRequired, + getCurrentQuery: React.PropTypes.func.isRequired, + isActive: React.PropTypes.func.isRequired }, - removeChangeListener: function (listener) { - _events.removeListener(CHANGE_EVENT, listener); - - // Automatically teardown when the last listener is removed. - if (EventEmitter.listenerCount(_events, CHANGE_EVENT) === 0) - PathStore.teardown(); - }, - - setup: function (location) { - // When using HistoryLocation, automatically fallback - // to RefreshLocation in browsers that do not support - // the HTML5 history API. - if (location === HistoryLocation && !supportsHistory()) - location = RefreshLocation; - - if (_location == null) { - _location = location; - - if (_location && typeof _location.setup === 'function') - _location.setup(notifyChange); - } else { - warning( - _location === location, - 'Cannot use location %s, already using %s', location, _location - ); - } + /** + * Returns the current URL path. + */ + getPath: function () { + return this.context.getCurrentPath(); }, - teardown: function () { - _events.removeAllListeners(CHANGE_EVENT); - - if (_location && typeof _location.teardown === 'function') - _location.teardown(); - - _location = null; + /** + * Returns an array of the routes that are currently active. + */ + getRoutes: function () { + return this.context.getCurrentRoutes(); }, /** - * Returns the location object currently in use. + * Returns the current URL path without the query string. */ - getLocation: function () { - return _location; + getPathname: function () { + return this.context.getCurrentPathname(); }, /** - * Returns the current URL path. + * Returns an object of the URL params that are currently active. */ - getCurrentPath: function () { - return _location.getCurrentPath(); + getParams: function () { + return this.context.getCurrentParams(); }, /** - * Returns the last known scroll position for the given path. + * Returns an object of the query params that are currently active. */ - getScrollPosition: function (path) { - return _scrollPositions[path] || { x: 0, y: 0 }; + getQuery: function () { + return this.context.getCurrentQuery(); }, - dispatchToken: LocationDispatcher.register(function (payload) { - var action = payload.action; - var currentPath = _location.getCurrentPath(); + /** + * A helper method to determine if a given route, params, and query + * are active. + */ + isActive: function (to, params, query) { + return this.context.isActive(to, params, query); + } - switch (action.type) { - case LocationActions.PUSH: - if (currentPath !== action.path) { - recordScrollPosition(currentPath); - _location.push(action.path); - } - break; +}; - case LocationActions.REPLACE: - if (currentPath !== action.path) { - recordScrollPosition(currentPath); - _location.replace(action.path); - } - break; +module.exports = State; - case LocationActions.POP: - recordScrollPosition(currentPath); - _location.pop(); - break; +},{}],19:[function(_dereq_,module,exports){ +var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); +var assign = _dereq_('react/lib/Object.assign'); +var Path = _dereq_('../utils/Path'); - case LocationActions.UPDATE_SCROLL: - updateScrollPosition(currentPath); - break; - } - }) +function routeIsActive(activeRoutes, routeName) { + return activeRoutes.some(function (route) { + return route.name === routeName; + }); +} -}; +function paramsAreActive(activeParams, params) { + for (var property in params) + if (String(activeParams[property]) !== String(params[property])) + return false; -module.exports = PathStore; + return true; +} -},{"../actions/LocationActions":1,"../dispatchers/LocationDispatcher":8,"../locations/HistoryLocation":12,"../locations/RefreshLocation":14,"../utils/supportsHistory":28,"events":30,"react/lib/warning":48}],19:[function(_dereq_,module,exports){ -var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); -var invariant = _dereq_('react/lib/invariant'); -var warning = _dereq_('react/lib/warning'); -var Path = _dereq_('../utils/Path'); +function queryIsActive(activeQuery, query) { + for (var property in query) + if (String(activeQuery[property]) !== String(query[property])) + return false; -var _namedRoutes = {}; + return true; +} /** - * The RouteStore contains a directory of all <Route>s in the system. It is - * used primarily for looking up routes by name so that <Link>s can use a - * route name in the "to" prop and users can use route names in `Router.transitionTo` - * and other high-level utility methods. + * Provides the router with context for Router.State. */ -var RouteStore = { +var StateContext = { /** - * Removes all references to <Route>s from the store. Should only ever - * really be used in tests to clear the store between test runs. + * Returns the current URL path + query string. */ - unregisterAllRoutes: function () { - _namedRoutes = {}; + getCurrentPath: function () { + return this.state.path; }, /** - * Removes the reference to the given <Route> and all of its children - * from the store. + * Returns a read-only array of the currently active routes. */ - unregisterRoute: function (route) { - var props = route.props; - - if (props.name) - delete _namedRoutes[props.name]; - - React.Children.forEach(props.children, RouteStore.unregisterRoute); + getCurrentRoutes: function () { + return this.state.routes.slice(0); }, /** - * Registers a <Route> and all of its children with the store. Also, - * does some normalization and validation on route props. + * Returns the current URL path without the query string. */ - registerRoute: function (route, parentRoute) { - // Note: parentRoute may be a <Route> _or_ a <Routes>. - var props = route.props; - - invariant( - React.isValidClass(props.handler), - 'The handler for the "%s" route must be a valid React class', - props.name || props.path - ); - - var parentPath = (parentRoute && parentRoute.props.path) || '/'; - - if ((props.path || props.name) && !props.isDefault && !props.catchAll) { - var path = props.path || props.name; - - // Relative paths extend their parent. - if (!Path.isAbsolute(path)) - path = Path.join(parentPath, path); - - props.path = Path.normalize(path); - } else { - props.path = parentPath; - - if (props.catchAll) - props.path += '*'; - } - - props.paramNames = Path.extractParamNames(props.path); - - // Make sure the route's path has all params its parent needs. - if (parentRoute && Array.isArray(parentRoute.props.paramNames)) { - parentRoute.props.paramNames.forEach(function (paramName) { - invariant( - props.paramNames.indexOf(paramName) !== -1, - 'The nested route path "%s" is missing the "%s" parameter of its parent path "%s"', - props.path, paramName, parentRoute.props.path - ); - }); - } - - // Make sure the route can be looked up by <Link>s. - if (props.name) { - var existingRoute = _namedRoutes[props.name]; - - invariant( - !existingRoute || route === existingRoute, - 'You cannot use the name "%s" for more than one route', - props.name - ); - - _namedRoutes[props.name] = route; - } - - if (props.catchAll) { - invariant( - parentRoute, - '<NotFoundRoute> must have a parent <Route>' - ); - - invariant( - parentRoute.props.notFoundRoute == null, - 'You may not have more than one <NotFoundRoute> per <Route>' - ); - - parentRoute.props.notFoundRoute = route; - - return null; - } - - if (props.isDefault) { - invariant( - parentRoute, - '<DefaultRoute> must have a parent <Route>' - ); - - invariant( - parentRoute.props.defaultRoute == null, - 'You may not have more than one <DefaultRoute> per <Route>' - ); - - parentRoute.props.defaultRoute = route; - - return null; - } + getCurrentPathname: function () { + return this.state.pathname; + }, - // Make sure children is an array. - props.children = RouteStore.registerChildren(props.children, route); + /** + * Returns a read-only object of the currently active URL parameters. + */ + getCurrentParams: function () { + return assign({}, this.state.params); + }, - return route; + /** + * Returns a read-only object of the currently active query parameters. + */ + getCurrentQuery: function () { + return assign({}, this.state.query); }, /** - * Registers many children routes at once, always returning an array. + * Returns true if the given route, params, and query are active. */ - registerChildren: function (children, parentRoute) { - var routes = []; + isActive: function (to, params, query) { + if (Path.isAbsolute(to)) + return to === this.state.path; - React.Children.forEach(children, function (child) { - // Exclude <DefaultRoute>s. - if (child = RouteStore.registerRoute(child, parentRoute)) - routes.push(child); - }); + return routeIsActive(this.state.routes, to) && + paramsAreActive(this.state.params, params) && + (query == null || queryIsActive(this.state.query, query)); + }, - return routes; + childContextTypes: { + getCurrentPath: React.PropTypes.func.isRequired, + getCurrentRoutes: React.PropTypes.func.isRequired, + getCurrentPathname: React.PropTypes.func.isRequired, + getCurrentParams: React.PropTypes.func.isRequired, + getCurrentQuery: React.PropTypes.func.isRequired, + isActive: React.PropTypes.func.isRequired }, - /** - * Returns the Route object with the given name, if one exists. - */ - getRouteByName: function (routeName) { - return _namedRoutes[routeName] || null; + getChildContext: function () { + return { + getCurrentPath: this.getCurrentPath, + getCurrentRoutes: this.getCurrentRoutes, + getCurrentPathname: this.getCurrentPathname, + getCurrentParams: this.getCurrentParams, + getCurrentQuery: this.getCurrentQuery, + isActive: this.isActive + }; } }; -module.exports = RouteStore; +module.exports = StateContext; -},{"../utils/Path":20,"react/lib/invariant":42,"react/lib/warning":48}],20:[function(_dereq_,module,exports){ +},{"../utils/Path":21,"react/lib/Object.assign":38}],20:[function(_dereq_,module,exports){ +/** + * Represents a cancellation caused by navigating away + * before the previous transition has fully resolved. + */ +function Cancellation() { } + +module.exports = Cancellation; + +},{}],21:[function(_dereq_,module,exports){ var invariant = _dereq_('react/lib/invariant'); var merge = _dereq_('qs/lib/utils').merge; var qs = _dereq_('qs'); -function encodeURL(url) { - return encodeURIComponent(url).replace(/%20/g, '+'); -} - -function decodeURL(url) { - return decodeURIComponent(url.replace(/\+/g, ' ')); -} - -function encodeURLPath(path) { - return String(path).split('/').map(encodeURL).join('/'); -} - -var paramMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$]*)|[*.()\[\]\\+|{}^$]/g; +var paramCompileMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$]*)|[*.()\[\]\\+|{}^$]/g; +var paramInjectMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$?]*[?]?)|[*]/g; +var paramInjectTrailingSlashMatcher = /\/\/\?|\/\?/g; var queryMatcher = /\?(.+)/; var _compiledPatterns = {}; @@ -1709,10 +1032,10 @@ var _compiledPatterns = {}; function compilePattern(pattern) { if (!(pattern in _compiledPatterns)) { var paramNames = []; - var source = pattern.replace(paramMatcher, function (match, paramName) { + var source = pattern.replace(paramCompileMatcher, function (match, paramName) { if (paramName) { paramNames.push(paramName); - return '([^./?#]+)'; + return '([^/?#]+)'; } else if (match === '*') { paramNames.push('splat'); return '(.*?)'; @@ -1733,6 +1056,20 @@ function compilePattern(pattern) { var Path = { /** + * Safely decodes special characters in the given URL path. + */ + decode: function (path) { + return decodeURI(path.replace(/\+/g, ' ')); + }, + + /** + * Safely encodes special characters in the given URL path. + */ + encode: function (path) { + return encodeURI(path).replace(/%20/g, '+'); + }, + + /** * Returns an array of the names of all parameters in the given pattern. */ extractParamNames: function (pattern) { @@ -1746,7 +1083,7 @@ var Path = { */ extractParams: function (pattern, path) { var object = compilePattern(pattern); - var match = decodeURL(path).match(object.matcher); + var match = path.match(object.matcher); if (!match) return null; @@ -1769,13 +1106,21 @@ var Path = { var splatIndex = 0; - return pattern.replace(paramMatcher, function (match, paramName) { + return pattern.replace(paramInjectMatcher, function (match, paramName) { paramName = paramName || 'splat'; - invariant( - params[paramName] != null, - 'Missing "' + paramName + '" parameter for path "' + pattern + '"' - ); + // If param is optional don't check for existence + if (paramName.slice(-1) !== '?') { + invariant( + params[paramName] != null, + 'Missing "' + paramName + '" parameter for path "' + pattern + '"' + ); + } else { + paramName = paramName.slice(0, -1); + + if (params[paramName] == null) + return ''; + } var segment; if (paramName === 'splat' && Array.isArray(params[paramName])) { @@ -1789,8 +1134,8 @@ var Path = { segment = params[paramName]; } - return encodeURLPath(segment); - }); + return segment; + }).replace(paramInjectTrailingSlashMatcher, '/'); }, /** @@ -1798,7 +1143,7 @@ var Path = { * in the given path, null if the path contains no query string. */ extractQuery: function (path) { - var match = decodeURL(path).match(queryMatcher); + var match = path.match(queryMatcher); return match && qs.parse(match[1]); }, @@ -1852,7 +1197,30 @@ var Path = { module.exports = Path; -},{"qs":34,"qs/lib/utils":38,"react/lib/invariant":42}],21:[function(_dereq_,module,exports){ +},{"qs":32,"qs/lib/utils":36,"react/lib/invariant":41}],22:[function(_dereq_,module,exports){ +var Promise = _dereq_('when/lib/Promise'); + +// TODO: Use process.env.NODE_ENV check + envify to enable +// when's promise monitor here when in dev. + +module.exports = Promise; + +},{"when/lib/Promise":43}],23:[function(_dereq_,module,exports){ +var PropTypes = { + + /** + * Requires that the value of a prop be falsy. + */ + falsy: function (props, propName, elementName) { + if (props[propName]) + return new Error('<' + elementName + '> may not have a "' + propName + '" prop'); + } + +}; + +module.exports = PropTypes; + +},{}],24:[function(_dereq_,module,exports){ /** * Encapsulates a redirect to the given route. */ @@ -1864,10 +1232,89 @@ function Redirect(to, params, query) { module.exports = Redirect; -},{}],22:[function(_dereq_,module,exports){ -var mixInto = _dereq_('react/lib/mixInto'); -var transitionTo = _dereq_('../actions/LocationActions').transitionTo; +},{}],25:[function(_dereq_,module,exports){ +var assign = _dereq_('react/lib/Object.assign'); +var reversedArray = _dereq_('./reversedArray'); var Redirect = _dereq_('./Redirect'); +var Promise = _dereq_('./Promise'); + +/** + * Runs all hook functions serially and calls callback(error) when finished. + * A hook may return a promise if it needs to execute asynchronously. + */ +function runHooks(hooks, callback) { + try { + var promise = hooks.reduce(function (promise, hook) { + // The first hook to use transition.wait makes the rest + // of the transition async from that point forward. + return promise ? promise.then(hook) : hook(); + }, null); + } catch (error) { + return callback(error); // Sync error. + } + + if (promise) { + // Use setTimeout to break the promise chain. + promise.then(function () { + setTimeout(callback); + }, function (error) { + setTimeout(function () { + callback(error); + }); + }); + } else { + callback(); + } +} + +/** + * Calls the willTransitionFrom hook of all handlers in the given matches + * serially in reverse with the transition object and the current instance of + * the route's handler, so that the deepest nested handlers are called first. + * Calls callback(error) when finished. + */ +function runTransitionFromHooks(transition, routes, components, callback) { + components = reversedArray(components); + + var hooks = reversedArray(routes).map(function (route, index) { + return function () { + var handler = route.handler; + + if (!transition.isAborted && handler.willTransitionFrom) + return handler.willTransitionFrom(transition, components[index]); + + var promise = transition._promise; + transition._promise = null; + + return promise; + }; + }); + + runHooks(hooks, callback); +} + +/** + * Calls the willTransitionTo hook of all handlers in the given matches + * serially with the transition object and any params that apply to that + * handler. Calls callback(error) when finished. + */ +function runTransitionToHooks(transition, routes, params, query, callback) { + var hooks = routes.map(function (route) { + return function () { + var handler = route.handler; + + if (!transition.isAborted && handler.willTransitionTo) + handler.willTransitionTo(transition, params, query); + + var promise = transition._promise; + transition._promise = null; + + return promise; + }; + }); + + runHooks(hooks, callback); +} /** * Encapsulates a transition to a given path. @@ -1875,15 +1322,22 @@ var Redirect = _dereq_('./Redirect'); * The willTransitionTo and willTransitionFrom handlers receive * an instance of this class as their first argument. */ -function Transition(path) { +function Transition(path, retry) { this.path = path; this.abortReason = null; this.isAborted = false; + this.retry = retry.bind(this); + this._promise = null; } -mixInto(Transition, { +assign(Transition.prototype, { abort: function (reason) { + if (this.isAborted) { + // First abort wins. + return; + } + this.abortReason = reason; this.isAborted = true; }, @@ -1892,763 +1346,747 @@ mixInto(Transition, { this.abort(new Redirect(to, params, query)); }, - retry: function () { - transitionTo(this.path); + wait: function (value) { + this._promise = Promise.resolve(value); + }, + + from: function (routes, components, callback) { + return runTransitionFromHooks(this, routes, components, callback); + }, + + to: function (routes, params, query, callback) { + return runTransitionToHooks(this, routes, params, query, callback); } }); module.exports = Transition; -},{"../actions/LocationActions":1,"./Redirect":21,"react/lib/mixInto":47}],23:[function(_dereq_,module,exports){ +},{"./Promise":22,"./Redirect":24,"./reversedArray":29,"react/lib/Object.assign":38}],26:[function(_dereq_,module,exports){ +var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); +var warning = _dereq_('react/lib/warning'); +var invariant = _dereq_('react/lib/invariant'); +var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM; +var ImitateBrowserBehavior = _dereq_('../behaviors/ImitateBrowserBehavior'); +var RouteHandler = _dereq_('../components/RouteHandler'); +var LocationActions = _dereq_('../actions/LocationActions'); +var HashLocation = _dereq_('../locations/HashLocation'); +var HistoryLocation = _dereq_('../locations/HistoryLocation'); +var RefreshLocation = _dereq_('../locations/RefreshLocation'); +var NavigationContext = _dereq_('../mixins/NavigationContext'); +var StateContext = _dereq_('../mixins/StateContext'); +var Scrolling = _dereq_('../mixins/Scrolling'); +var createRoutesFromChildren = _dereq_('./createRoutesFromChildren'); +var supportsHistory = _dereq_('./supportsHistory'); +var Transition = _dereq_('./Transition'); +var PropTypes = _dereq_('./PropTypes'); +var Redirect = _dereq_('./Redirect'); +var Cancellation = _dereq_('./Cancellation'); +var Path = _dereq_('./Path'); + /** - * Returns the current URL path from `window.location`, including query string + * The default location for new routers. */ -function getWindowPath() { - return window.location.pathname + window.location.search; +var DEFAULT_LOCATION = canUseDOM ? HashLocation : '/'; + +/** + * The default scroll behavior for new routers. + */ +var DEFAULT_SCROLL_BEHAVIOR = canUseDOM ? ImitateBrowserBehavior : null; + +/** + * The default error handler for new routers. + */ +function defaultErrorHandler(error) { + // Throw so we don't silently swallow async errors. + throw error; // This error probably originated in a transition hook. } -module.exports = getWindowPath; +/** + * The default aborted transition handler for new routers. + */ +function defaultAbortHandler(abortReason, location) { + if (typeof location === 'string') + throw new Error('Unhandled aborted transition! Reason: ' + abortReason); + + if (abortReason instanceof Cancellation) { + return; + } else if (abortReason instanceof Redirect) { + location.replace(this.makePath(abortReason.to, abortReason.params, abortReason.query)); + } else { + location.pop(); + } +} +function findMatch(pathname, routes, defaultRoute, notFoundRoute) { + var match, route, params; -},{}],24:[function(_dereq_,module,exports){ -module.exports = Function.prototype.call.bind(Object.prototype.hasOwnProperty); + for (var i = 0, len = routes.length; i < len; ++i) { + route = routes[i]; -},{}],25:[function(_dereq_,module,exports){ -var HashLocation = _dereq_('../locations/HashLocation'); -var PathStore = _dereq_('../stores/PathStore'); -var makePath = _dereq_('./makePath'); + // Check the subtree first to find the most deeply-nested match. + match = findMatch(pathname, route.childRoutes, route.defaultRoute, route.notFoundRoute); -/** - * Returns a string that may safely be used as the href of a - * link to the route with the given name. - */ -function makeHref(to, params, query) { - var path = makePath(to, params, query); + if (match != null) { + match.routes.unshift(route); + return match; + } - if (PathStore.getLocation() === HashLocation) - return '#' + path; + // No routes in the subtree matched, so check this route. + params = Path.extractParams(route.path, pathname); - return path; + if (params) + return createMatch(route, params); + } + + // No routes matched, so try the default route if there is one. + if (defaultRoute && (params = Path.extractParams(defaultRoute.path, pathname))) + return createMatch(defaultRoute, params); + + // Last attempt: does the "not found" route match? + if (notFoundRoute && (params = Path.extractParams(notFoundRoute.path, pathname))) + return createMatch(notFoundRoute, params); + + return match; } -module.exports = makeHref; +function createMatch(route, params) { + return { routes: [ route ], params: params }; +} -},{"../locations/HashLocation":11,"../stores/PathStore":18,"./makePath":26}],26:[function(_dereq_,module,exports){ -var invariant = _dereq_('react/lib/invariant'); -var RouteStore = _dereq_('../stores/RouteStore'); -var Path = _dereq_('./Path'); +function hasMatch(routes, route, prevParams, nextParams) { + return routes.some(function (r) { + if (r !== route) + return false; + + var paramNames = route.paramNames; + var paramName; + + for (var i = 0, len = paramNames.length; i < len; ++i) { + paramName = paramNames[i]; + + if (nextParams[paramName] !== prevParams[paramName]) + return false; + } + + return true; + }); +} /** - * Returns an absolute URL path created from the given route name, URL - * parameters, and query values. + * Creates and returns a new router using the given options. A router + * is a ReactComponent class that knows how to react to changes in the + * URL and keep the contents of the page in sync. + * + * Options may be any of the following: + * + * - routes (required) The route config + * - location The location to use. Defaults to HashLocation when + * the DOM is available, "/" otherwise + * - scrollBehavior The scroll behavior to use. Defaults to ImitateBrowserBehavior + * when the DOM is available, null otherwise + * - onError A function that is used to handle errors + * - onAbort A function that is used to handle aborted transitions + * + * When rendering in a server-side environment, the location should simply + * be the URL path that was used in the request, including the query string. */ -function makePath(to, params, query) { - var path; - if (Path.isAbsolute(to)) { - path = Path.normalize(to); - } else { - var route = RouteStore.getRouteByName(to); +function createRouter(options) { + options = options || {}; - invariant( - route, - 'Unable to find a route named "' + to + '". Make sure you have ' + - 'a <Route name="' + to + '"> defined somewhere in your routes' - ); + if (typeof options === 'function') { + options = { routes: options }; // Router.create(<Route>) + } else if (Array.isArray(options)) { + options = { routes: options }; // Router.create([ <Route>, <Route> ]) + } - path = route.props.path; + var routes = []; + var namedRoutes = {}; + var components = []; + var location = options.location || DEFAULT_LOCATION; + var scrollBehavior = options.scrollBehavior || DEFAULT_SCROLL_BEHAVIOR; + var onError = options.onError || defaultErrorHandler; + var onAbort = options.onAbort || defaultAbortHandler; + var state = {}; + var nextState = {}; + var pendingTransition = null; + + function updateState() { + state = nextState; + nextState = {}; } - return Path.withQuery(Path.injectParams(path, params), query); -} + // Automatically fall back to full page refreshes in + // browsers that don't support the HTML history API. + if (location === HistoryLocation && !supportsHistory()) + location = RefreshLocation; -module.exports = makePath; + var router = React.createClass({ -},{"../stores/RouteStore":19,"./Path":20,"react/lib/invariant":42}],27:[function(_dereq_,module,exports){ -var Promise = _dereq_('when/lib/Promise'); + displayName: 'Router', -/** - * Resolves all values in asyncState and calls the setState - * function with new state as they resolve. Returns a promise - * that resolves after all values are resolved. - */ -function resolveAsyncState(asyncState, setState) { - if (asyncState == null) - return Promise.resolve(); - - var keys = Object.keys(asyncState); - - return Promise.all( - keys.map(function (key) { - return Promise.resolve(asyncState[key]).then(function (value) { - var newState = {}; - newState[key] = value; - setState(newState); - }); - }) - ); -} + mixins: [ NavigationContext, StateContext, Scrolling ], -module.exports = resolveAsyncState; + statics: { -},{"when/lib/Promise":49}],28:[function(_dereq_,module,exports){ -function supportsHistory() { - /*! taken from modernizr - * https://github.com/Modernizr/Modernizr/blob/master/LICENSE - * https://github.com/Modernizr/Modernizr/blob/master/feature-detects/history.js - */ - var ua = navigator.userAgent; - if ((ua.indexOf('Android 2.') !== -1 || - (ua.indexOf('Android 4.0') !== -1)) && - ua.indexOf('Mobile Safari') !== -1 && - ua.indexOf('Chrome') === -1) { - return false; - } - return (window.history && 'pushState' in window.history); -} + defaultRoute: null, + notFoundRoute: null, + + /** + * Adds routes to this router from the given children object (see ReactChildren). + */ + addRoutes: function (children) { + routes.push.apply(routes, createRoutesFromChildren(children, this, namedRoutes)); + }, + + /** + * Returns an absolute URL path created from the given route + * name, URL parameters, and query. + */ + makePath: function (to, params, query) { + var path; + if (Path.isAbsolute(to)) { + path = Path.normalize(to); + } else { + var route = namedRoutes[to]; + + invariant( + route, + 'Unable to find <Route name="%s">', + to + ); + + path = route.path; + } -module.exports = supportsHistory; + return Path.withQuery(Path.injectParams(path, params), query); + }, + + /** + * Returns a string that may safely be used as the href of a link + * to the route with the given name, URL parameters, and query. + */ + makeHref: function (to, params, query) { + var path = this.makePath(to, params, query); + return (location === HashLocation) ? '#' + path : path; + }, + + /** + * Transitions to the URL specified in the arguments by pushing + * a new URL onto the history stack. + */ + transitionTo: function (to, params, query) { + invariant( + typeof location !== 'string', + 'You cannot use transitionTo with a static location' + ); -},{}],29:[function(_dereq_,module,exports){ -function withoutProperties(object, properties) { - var result = {}; + var path = this.makePath(to, params, query); - for (var property in object) { - if (object.hasOwnProperty(property) && !properties[property]) - result[property] = object[property]; - } + if (pendingTransition) { + // Replace so pending location does not stay in history. + location.replace(path); + } else { + location.push(path); + } + }, - return result; -} + /** + * Transitions to the URL specified in the arguments by replacing + * the current URL in the history stack. + */ + replaceWith: function (to, params, query) { + invariant( + typeof location !== 'string', + 'You cannot use replaceWith with a static location' + ); -module.exports = withoutProperties; + location.replace(this.makePath(to, params, query)); + }, -},{}],30:[function(_dereq_,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -function EventEmitter() { - this._events = this._events || {}; - this._maxListeners = this._maxListeners || undefined; -} -module.exports = EventEmitter; + /** + * Transitions to the previous URL. + */ + goBack: function () { + invariant( + typeof location !== 'string', + 'You cannot use goBack with a static location' + ); -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; + location.pop(); + }, + + /** + * Performs a match of the given pathname against this router and returns an object + * with the { routes, params } that match. Returns null if no match can be made. + */ + match: function (pathname) { + return findMatch(pathname, routes, this.defaultRoute, this.notFoundRoute) || null; + }, + + /** + * Performs a transition to the given path and calls callback(error, abortReason) + * when the transition is finished. If both arguments are null the router's state + * was updated. Otherwise the transition did not complete. + * + * In a transition, a router first determines which routes are involved by beginning + * with the current route, up the route tree to the first parent route that is shared + * with the destination route, and back down the tree to the destination route. The + * willTransitionFrom hook is invoked on all route handlers we're transitioning away + * from, in reverse nesting order. Likewise, the willTransitionTo hook is invoked on + * all route handlers we're transitioning to. + * + * Both willTransitionFrom and willTransitionTo hooks may either abort or redirect the + * transition. To resolve asynchronously, they may use transition.wait(promise). If no + * hooks wait, the transition is fully synchronous. + */ + dispatch: function (path, action, callback) { + if (pendingTransition) { + pendingTransition.abort(new Cancellation); + pendingTransition = null; + } -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._maxListeners = undefined; + var prevPath = state.path; + if (prevPath === path) + return; // Nothing to do! -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -EventEmitter.defaultMaxListeners = 10; + // Record the scroll position as early as possible to + // get it before browsers try update it automatically. + if (prevPath && action !== LocationActions.REPLACE) + this.recordScrollPosition(prevPath); -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; + var pathname = Path.withoutQuery(path); + var match = this.match(pathname); -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; + warning( + match != null, + 'No route matches path "%s". Make sure you have <Route path="%s"> somewhere in your routes', + path, path + ); - if (!this._events) - this._events = {}; + if (match == null) + match = {}; - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } else { - throw TypeError('Uncaught, unspecified "error" event.'); - } - return false; - } - } + var prevRoutes = state.routes || []; + var prevParams = state.params || {}; - handler = this._events[type]; + var nextRoutes = match.routes || []; + var nextParams = match.params || {}; + var nextQuery = Path.extractQuery(path) || {}; - if (isUndefined(handler)) - return false; + var fromRoutes, toRoutes; + if (prevRoutes.length) { + fromRoutes = prevRoutes.filter(function (route) { + return !hasMatch(nextRoutes, route, prevParams, nextParams); + }); - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - handler.apply(this, args); - } - } else if (isObject(handler)) { - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } + toRoutes = nextRoutes.filter(function (route) { + return !hasMatch(prevRoutes, route, prevParams, nextParams); + }); + } else { + fromRoutes = []; + toRoutes = nextRoutes; + } - return true; -}; + var transition = new Transition(path, this.replaceWith.bind(this, path)); + pendingTransition = transition; -EventEmitter.prototype.addListener = function(type, listener) { - var m; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events) - this._events = {}; - - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); - - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - var m; - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; - } else { - m = EventEmitter.defaultMaxListeners; - } + transition.from(fromRoutes, components, function (error) { + if (error || transition.isAborted) + return callback.call(router, error, transition); - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } - } + transition.to(toRoutes, nextParams, nextQuery, function (error) { + if (error || transition.isAborted) + return callback.call(router, error, transition); - return this; -}; + nextState.path = path; + nextState.action = action; + nextState.pathname = pathname; + nextState.routes = nextRoutes; + nextState.params = nextParams; + nextState.query = nextQuery; -EventEmitter.prototype.on = EventEmitter.prototype.addListener; + callback.call(router, null, transition); + }); + }); + }, + + /** + * Starts this router and calls callback(router, state) when the route changes. + * + * If the router's location is static (i.e. a URL path in a server environment) + * the callback is called only once. Otherwise, the location should be one of the + * Router.*Location objects (e.g. Router.HashLocation or Router.HistoryLocation). + */ + run: function (callback) { + function dispatchHandler(error, transition) { + pendingTransition = null; + + if (error) { + onError.call(router, error); + } else if (transition.isAborted) { + onAbort.call(router, transition.abortReason, location); + } else { + callback.call(router, router, nextState); + } + } -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); + if (typeof location === 'string') { + warning( + !canUseDOM || "production" === 'test', + 'You should not use a static location in a DOM environment because ' + + 'the router will not be kept in sync with the current URL' + ); + + // Dispatch the location. + router.dispatch(location, null, dispatchHandler); + } else { + invariant( + canUseDOM, + 'You cannot use %s in a non-DOM environment', + location + ); + + // Listen for changes to the location. + function changeListener(change) { + router.dispatch(change.path, change.type, dispatchHandler); + } + + if (location.addChangeListener) + location.addChangeListener(changeListener); + + // Bootstrap using the current path. + router.dispatch(location.getCurrentPath(), null, dispatchHandler); + } + } - var fired = false; + }, - function g() { - this.removeListener(type, g); + propTypes: { + children: PropTypes.falsy + }, - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } + getLocation: function () { + return location; + }, - g.listener = listener; - this.on(type, g); + getScrollBehavior: function () { + return scrollBehavior; + }, - return this; -}; + getRouteAtDepth: function (depth) { + var routes = this.state.routes; + return routes && routes[depth]; + }, -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; + getRouteComponents: function () { + return components; + }, - if (!isFunction(listener)) - throw TypeError('listener must be a function'); + getInitialState: function () { + updateState(); + return state; + }, - if (!this._events || !this._events[type]) - return this; + componentWillReceiveProps: function () { + updateState(); + this.setState(state); + }, - list = this._events[type]; - length = list.length; - position = -1; + render: function () { + return this.getRouteAtDepth(0) ? React.createElement(RouteHandler, this.props) : null; + }, - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); + childContextTypes: { + getRouteAtDepth: React.PropTypes.func.isRequired, + getRouteComponents: React.PropTypes.func.isRequired, + routeHandlers: React.PropTypes.array.isRequired + }, - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } + getChildContext: function () { + return { + getRouteComponents: this.getRouteComponents, + getRouteAtDepth: this.getRouteAtDepth, + routeHandlers: [ this ] + }; } - if (position < 0) - return this; + }); - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } + if (options.routes) + router.addRoutes(options.routes); - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } + return router; +} - return this; -}; +module.exports = createRouter; -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; +},{"../actions/LocationActions":1,"../behaviors/ImitateBrowserBehavior":2,"../components/RouteHandler":9,"../locations/HashLocation":11,"../locations/HistoryLocation":12,"../locations/RefreshLocation":13,"../mixins/NavigationContext":16,"../mixins/Scrolling":17,"../mixins/StateContext":19,"./Cancellation":20,"./Path":21,"./PropTypes":23,"./Redirect":24,"./Transition":25,"./createRoutesFromChildren":27,"./supportsHistory":31,"react/lib/ExecutionEnvironment":37,"react/lib/invariant":41,"react/lib/warning":42}],27:[function(_dereq_,module,exports){ +var React = (typeof window !== "undefined" ? window.React : typeof global !== "undefined" ? global.React : null); +var warning = _dereq_('react/lib/warning'); +var invariant = _dereq_('react/lib/invariant'); +var DefaultRoute = _dereq_('../components/DefaultRoute'); +var NotFoundRoute = _dereq_('../components/NotFoundRoute'); +var Redirect = _dereq_('../components/Redirect'); +var Route = _dereq_('../components/Route'); +var Path = _dereq_('./Path'); - if (!this._events) - return this; +var CONFIG_ELEMENT_TYPES = [ + DefaultRoute.type, + NotFoundRoute.type, + Redirect.type, + Route.type +]; - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } +function createRedirectHandler(to, _params, _query) { + return React.createClass({ + statics: { + willTransitionTo: function (transition, params, query) { + transition.redirect(to, _params || params, _query || query); + } + }, - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); + render: function () { + return null; } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } + }); +} - listeners = this._events[type]; +function checkPropTypes(componentName, propTypes, props) { + for (var propName in propTypes) { + if (propTypes.hasOwnProperty(propName)) { + var error = propTypes[propName](props, propName, componentName); - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); + if (error instanceof Error) + warning(false, error.message); + } } - delete this._events[type]; +} - return this; -}; +function createRoute(element, parentRoute, namedRoutes) { + var type = element.type; + var props = element.props; + var componentName = (type && type.displayName) || 'UnknownComponent'; -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; + invariant( + CONFIG_ELEMENT_TYPES.indexOf(type) !== -1, + 'Unrecognized route configuration element "<%s>"', + componentName + ); -EventEmitter.listenerCount = function(emitter, type) { - var ret; - if (!emitter._events || !emitter._events[type]) - ret = 0; - else if (isFunction(emitter._events[type])) - ret = 1; - else - ret = emitter._events[type].length; - return ret; -}; + if (type.propTypes) + checkPropTypes(componentName, type.propTypes, props); -function isFunction(arg) { - return typeof arg === 'function'; -} + var route = { name: props.name }; -function isNumber(arg) { - return typeof arg === 'number'; -} + if (props.ignoreScrollBehavior) { + route.ignoreScrollBehavior = true; + } -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} + if (type === Redirect.type) { + route.handler = createRedirectHandler(props.to, props.params, props.query); + props.path = props.path || props.from || '*'; + } else { + route.handler = props.handler; + } -function isUndefined(arg) { - return arg === void 0; -} + var parentPath = (parentRoute && parentRoute.path) || '/'; -},{}],31:[function(_dereq_,module,exports){ -/** - * Copyright (c) 2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ + if ((props.path || props.name) && type !== DefaultRoute.type && type !== NotFoundRoute.type) { + var path = props.path || props.name; -module.exports.Dispatcher = _dereq_('./lib/Dispatcher') + // Relative paths extend their parent. + if (!Path.isAbsolute(path)) + path = Path.join(parentPath, path); -},{"./lib/Dispatcher":32}],32:[function(_dereq_,module,exports){ -/* - * Copyright (c) 2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule Dispatcher - * @typechecks - */ + route.path = Path.normalize(path); + } else { + route.path = parentPath; -var invariant = _dereq_('./invariant'); + if (type === NotFoundRoute.type) + route.path += '*'; + } -var _lastID = 1; -var _prefix = 'ID_'; + route.paramNames = Path.extractParamNames(route.path); -/** - * Dispatcher is used to broadcast payloads to registered callbacks. This is - * different from generic pub-sub systems in two ways: - * - * 1) Callbacks are not subscribed to particular events. Every payload is - * dispatched to every registered callback. - * 2) Callbacks can be deferred in whole or part until other callbacks have - * been executed. - * - * For example, consider this hypothetical flight destination form, which - * selects a default city when a country is selected: - * - * var flightDispatcher = new Dispatcher(); - * - * // Keeps track of which country is selected - * var CountryStore = {country: null}; - * - * // Keeps track of which city is selected - * var CityStore = {city: null}; - * - * // Keeps track of the base flight price of the selected city - * var FlightPriceStore = {price: null} - * - * When a user changes the selected city, we dispatch the payload: - * - * flightDispatcher.dispatch({ - * actionType: 'city-update', - * selectedCity: 'paris' - * }); - * - * This payload is digested by `CityStore`: - * - * flightDispatcher.register(function(payload) { - * if (payload.actionType === 'city-update') { - * CityStore.city = payload.selectedCity; - * } - * }); - * - * When the user selects a country, we dispatch the payload: - * - * flightDispatcher.dispatch({ - * actionType: 'country-update', - * selectedCountry: 'australia' - * }); - * - * This payload is digested by both stores: - * - * CountryStore.dispatchToken = flightDispatcher.register(function(payload) { - * if (payload.actionType === 'country-update') { - * CountryStore.country = payload.selectedCountry; - * } - * }); - * - * When the callback to update `CountryStore` is registered, we save a reference - * to the returned token. Using this token with `waitFor()`, we can guarantee - * that `CountryStore` is updated before the callback that updates `CityStore` - * needs to query its data. - * - * CityStore.dispatchToken = flightDispatcher.register(function(payload) { - * if (payload.actionType === 'country-update') { - * // `CountryStore.country` may not be updated. - * flightDispatcher.waitFor([CountryStore.dispatchToken]); - * // `CountryStore.country` is now guaranteed to be updated. - * - * // Select the default city for the new country - * CityStore.city = getDefaultCityForCountry(CountryStore.country); - * } - * }); - * - * The usage of `waitFor()` can be chained, for example: - * - * FlightPriceStore.dispatchToken = - * flightDispatcher.register(function(payload) { - * switch (payload.actionType) { - * case 'country-update': - * flightDispatcher.waitFor([CityStore.dispatchToken]); - * FlightPriceStore.price = - * getFlightPriceStore(CountryStore.country, CityStore.city); - * break; - * - * case 'city-update': - * FlightPriceStore.price = - * FlightPriceStore(CountryStore.country, CityStore.city); - * break; - * } - * }); - * - * The `country-update` payload will be guaranteed to invoke the stores' - * registered callbacks in order: `CountryStore`, `CityStore`, then - * `FlightPriceStore`. - */ + // Make sure the route's path has all params its parent needs. + if (parentRoute && Array.isArray(parentRoute.paramNames)) { + parentRoute.paramNames.forEach(function (paramName) { + invariant( + route.paramNames.indexOf(paramName) !== -1, + 'The nested route path "%s" is missing the "%s" parameter of its parent path "%s"', + route.path, paramName, parentRoute.path + ); + }); + } + + // Make sure the route can be looked up by <Link>s. + if (props.name) { + invariant( + namedRoutes[props.name] == null, + 'You cannot use the name "%s" for more than one route', + props.name + ); - function Dispatcher() {"use strict"; - this.$Dispatcher_callbacks = {}; - this.$Dispatcher_isPending = {}; - this.$Dispatcher_isHandled = {}; - this.$Dispatcher_isDispatching = false; - this.$Dispatcher_pendingPayload = null; + namedRoutes[props.name] = route; } - /** - * Registers a callback to be invoked with every dispatched payload. Returns - * a token that can be used with `waitFor()`. - * - * @param {function} callback - * @return {string} - */ - Dispatcher.prototype.register=function(callback) {"use strict"; - var id = _prefix + _lastID++; - this.$Dispatcher_callbacks[id] = callback; - return id; - }; + // Handle <NotFoundRoute>. + if (type === NotFoundRoute.type) { + invariant( + parentRoute, + '<NotFoundRoute> must have a parent <Route>' + ); - /** - * Removes a callback based on its token. - * - * @param {string} id - */ - Dispatcher.prototype.unregister=function(id) {"use strict"; invariant( - this.$Dispatcher_callbacks[id], - 'Dispatcher.unregister(...): `%s` does not map to a registered callback.', - id + parentRoute.notFoundRoute == null, + 'You may not have more than one <NotFoundRoute> per <Route>' ); - delete this.$Dispatcher_callbacks[id]; - }; - /** - * Waits for the callbacks specified to be invoked before continuing execution - * of the current callback. This method should only be used by a callback in - * response to a dispatched payload. - * - * @param {array<string>} ids - */ - Dispatcher.prototype.waitFor=function(ids) {"use strict"; + parentRoute.notFoundRoute = route; + + return null; + } + + // Handle <DefaultRoute>. + if (type === DefaultRoute.type) { invariant( - this.$Dispatcher_isDispatching, - 'Dispatcher.waitFor(...): Must be invoked while dispatching.' + parentRoute, + '<DefaultRoute> must have a parent <Route>' ); - for (var ii = 0; ii < ids.length; ii++) { - var id = ids[ii]; - if (this.$Dispatcher_isPending[id]) { - invariant( - this.$Dispatcher_isHandled[id], - 'Dispatcher.waitFor(...): Circular dependency detected while ' + - 'waiting for `%s`.', - id - ); - continue; - } - invariant( - this.$Dispatcher_callbacks[id], - 'Dispatcher.waitFor(...): `%s` does not map to a registered callback.', - id - ); - this.$Dispatcher_invokeCallback(id); - } - }; - /** - * Dispatches a payload to all registered callbacks. - * - * @param {object} payload - */ - Dispatcher.prototype.dispatch=function(payload) {"use strict"; invariant( - !this.$Dispatcher_isDispatching, - 'Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.' + parentRoute.defaultRoute == null, + 'You may not have more than one <DefaultRoute> per <Route>' ); - this.$Dispatcher_startDispatching(payload); - try { - for (var id in this.$Dispatcher_callbacks) { - if (this.$Dispatcher_isPending[id]) { - continue; - } - this.$Dispatcher_invokeCallback(id); - } - } finally { - this.$Dispatcher_stopDispatching(); - } - }; - /** - * Is this Dispatcher currently dispatching. - * - * @return {boolean} - */ - Dispatcher.prototype.isDispatching=function() {"use strict"; - return this.$Dispatcher_isDispatching; - }; + parentRoute.defaultRoute = route; - /** - * Call the callback stored with the given id. Also do some internal - * bookkeeping. - * - * @param {string} id - * @internal - */ - Dispatcher.prototype.$Dispatcher_invokeCallback=function(id) {"use strict"; - this.$Dispatcher_isPending[id] = true; - this.$Dispatcher_callbacks[id](this.$Dispatcher_pendingPayload); - this.$Dispatcher_isHandled[id] = true; - }; + return null; + } - /** - * Set up bookkeeping needed when dispatching. - * - * @param {object} payload - * @internal - */ - Dispatcher.prototype.$Dispatcher_startDispatching=function(payload) {"use strict"; - for (var id in this.$Dispatcher_callbacks) { - this.$Dispatcher_isPending[id] = false; - this.$Dispatcher_isHandled[id] = false; - } - this.$Dispatcher_pendingPayload = payload; - this.$Dispatcher_isDispatching = true; - }; + route.childRoutes = createRoutesFromChildren(props.children, route, namedRoutes); - /** - * Clear bookkeeping used for dispatching. - * - * @internal - */ - Dispatcher.prototype.$Dispatcher_stopDispatching=function() {"use strict"; - this.$Dispatcher_pendingPayload = null; - this.$Dispatcher_isDispatching = false; - }; + return route; +} + +/** + * Creates and returns an array of route objects from the given ReactChildren. + */ +function createRoutesFromChildren(children, parentRoute, namedRoutes) { + var routes = []; + React.Children.forEach(children, function (child) { + // Exclude <DefaultRoute>s and <NotFoundRoute>s. + if (child = createRoute(child, parentRoute, namedRoutes)) + routes.push(child); + }); + + return routes; +} -module.exports = Dispatcher; +module.exports = createRoutesFromChildren; + +},{"../components/DefaultRoute":4,"../components/NotFoundRoute":6,"../components/Redirect":7,"../components/Route":8,"./Path":21,"react/lib/invariant":41,"react/lib/warning":42}],28:[function(_dereq_,module,exports){ +var invariant = _dereq_('react/lib/invariant'); +var canUseDOM = _dereq_('react/lib/ExecutionEnvironment').canUseDOM; -},{"./invariant":33}],33:[function(_dereq_,module,exports){ /** - * Copyright (c) 2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule invariant + * Returns the current scroll position of the window as { x, y }. */ +function getWindowScrollPosition() { + invariant( + canUseDOM, + 'Cannot get current scroll position without a DOM' + ); -"use strict"; + return { + x: window.scrollX, + y: window.scrollY + }; +} + +module.exports = getWindowScrollPosition; + +},{"react/lib/ExecutionEnvironment":37,"react/lib/invariant":41}],29:[function(_dereq_,module,exports){ +function reversedArray(array) { + return array.slice(0).reverse(); +} + +module.exports = reversedArray; + +},{}],30:[function(_dereq_,module,exports){ +var createRouter = _dereq_('./createRouter'); /** - * Use invariant() to assert state which your program assumes to be true. + * A high-level convenience method that creates, configures, and + * runs a router in one shot. The method signature is: * - * Provide sprintf-style format (only %s is supported) and arguments - * to provide information about what broke and what you were - * expecting. + * Router.run(routes[, location ], callback); * - * The invariant message will be stripped in production, but the invariant - * will remain to ensure logic does not differ in production. + * Using `window.location.hash` to manage the URL, you could do: + * + * Router.run(routes, function (Handler) { + * React.render(<Handler/>, document.body); + * }); + * + * Using HTML5 history and a custom "cursor" prop: + * + * Router.run(routes, Router.HistoryLocation, function (Handler) { + * React.render(<Handler cursor={cursor}/>, document.body); + * }); + * + * Returns the newly created router. + * + * Note: If you need to specify further options for your router such + * as error/abort handling or custom scroll behavior, use Router.create + * instead. + * + * var router = Router.create(options); + * router.run(function (Handler) { + * // ... + * }); */ - -var invariant = function(condition, format, a, b, c, d, e, f) { - if (false) { - if (format === undefined) { - throw new Error('invariant requires an error message argument'); - } +function runRouter(routes, location, callback) { + if (typeof location === 'function') { + callback = location; + location = null; } - if (!condition) { - var error; - if (format === undefined) { - error = new Error( - 'Minified exception occurred; use the non-minified dev environment ' + - 'for the full error message and additional helpful warnings.' - ); - } else { - var args = [a, b, c, d, e, f]; - var argIndex = 0; - error = new Error( - 'Invariant Violation: ' + - format.replace(/%s/g, function() { return args[argIndex++]; }) - ); - } + var router = createRouter({ + routes: routes, + location: location + }); - error.framesToPop = 1; // we don't care about invariant's own frame - throw error; + router.run(callback); + + return router; +} + +module.exports = runRouter; + +},{"./createRouter":26}],31:[function(_dereq_,module,exports){ +function supportsHistory() { + /*! taken from modernizr + * https://github.com/Modernizr/Modernizr/blob/master/LICENSE + * https://github.com/Modernizr/Modernizr/blob/master/feature-detects/history.js + */ + var ua = navigator.userAgent; + if ((ua.indexOf('Android 2.') !== -1 || + (ua.indexOf('Android 4.0') !== -1)) && + ua.indexOf('Mobile Safari') !== -1 && + ua.indexOf('Chrome') === -1) { + return false; } -}; + return (window.history && 'pushState' in window.history); +} -module.exports = invariant; +module.exports = supportsHistory; -},{}],34:[function(_dereq_,module,exports){ +},{}],32:[function(_dereq_,module,exports){ module.exports = _dereq_('./lib'); -},{"./lib":35}],35:[function(_dereq_,module,exports){ +},{"./lib":33}],33:[function(_dereq_,module,exports){ // Load modules var Stringify = _dereq_('./stringify'); @@ -2665,7 +2103,7 @@ module.exports = { parse: Parse }; -},{"./parse":36,"./stringify":37}],36:[function(_dereq_,module,exports){ +},{"./parse":34,"./stringify":35}],34:[function(_dereq_,module,exports){ // Load modules var Utils = _dereq_('./utils'); @@ -2821,7 +2259,7 @@ module.exports = function (str, options) { return Utils.compact(obj); }; -},{"./utils":38}],37:[function(_dereq_,module,exports){ +},{"./utils":36}],35:[function(_dereq_,module,exports){ // Load modules var Utils = _dereq_('./utils'); @@ -2881,7 +2319,7 @@ module.exports = function (obj, options) { return keys.join(delimiter); }; -},{"./utils":38}],38:[function(_dereq_,module,exports){ +},{"./utils":36}],36:[function(_dereq_,module,exports){ // Load modules @@ -3022,21 +2460,14 @@ exports.isBuffer = function (obj) { } }; -},{}],39:[function(_dereq_,module,exports){ +},{}],37:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ExecutionEnvironment */ @@ -3074,83 +2505,104 @@ var ExecutionEnvironment = { module.exports = ExecutionEnvironment; -},{}],40:[function(_dereq_,module,exports){ +},{}],38:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * - * @providesModule copyProperties + * @providesModule Object.assign */ -/** - * Copy properties from one or more objects (up to 5) into the first object. - * This is a shallow copy. It mutates the first object and also returns it. - * - * NOTE: `arguments` has a very significant performance penalty, which is why - * we don't support unlimited arguments. - */ -function copyProperties(obj, a, b, c, d, e, f) { - obj = obj || {}; +// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign - if ("production" !== "production") { - if (f) { - throw new Error('Too many arguments passed to copyProperties'); - } +function assign(target, sources) { + if (target == null) { + throw new TypeError('Object.assign target cannot be null or undefined'); } - var args = [a, b, c, d, e]; - var ii = 0, v; - while (args[ii]) { - v = args[ii++]; - for (var k in v) { - obj[k] = v[k]; + var to = Object(target); + var hasOwnProperty = Object.prototype.hasOwnProperty; + + for (var nextIndex = 1; nextIndex < arguments.length; nextIndex++) { + var nextSource = arguments[nextIndex]; + if (nextSource == null) { + continue; } - // IE ignores toString in object iteration.. See: - // webreflection.blogspot.com/2007/07/quick-fix-internet-explorer-and.html - if (v.hasOwnProperty && v.hasOwnProperty('toString') && - (typeof v.toString != 'undefined') && (obj.toString !== v.toString)) { - obj.toString = v.toString; + var from = Object(nextSource); + + // We don't currently support accessors nor proxies. Therefore this + // copy cannot throw. If we ever supported this then we must handle + // exceptions and side-effects. We don't support symbols so they won't + // be transferred. + + for (var key in from) { + if (hasOwnProperty.call(from, key)) { + to[key] = from[key]; + } } } - return obj; -} + return to; +}; -module.exports = copyProperties; +module.exports = assign; -},{}],41:[function(_dereq_,module,exports){ +},{}],39:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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 + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * - * http://www.apache.org/licenses/LICENSE-2.0 + * @providesModule cx + */ + +/** + * This function is used to mark string literals representing CSS class names + * so that they can be transformed statically. This allows for modularization + * and minification of CSS class names. + * + * In static_upstream, this function is actually implemented, but it should + * eventually be replaced with something more descriptive, and the transform + * that is used in the main stack should be ported for use elsewhere. + * + * @param string|object className to modularize, or an object of key/values. + * In the object case, the values are conditions that + * determine if the className keys should be included. + * @param [string ...] Variable list of classNames in the string case. + * @return string Renderable space-separated CSS className. + */ +function cx(classNames) { + if (typeof classNames == 'object') { + return Object.keys(classNames).filter(function(className) { + return classNames[className]; + }).join(' '); + } else { + return Array.prototype.join.call(arguments, ' '); + } +} + +module.exports = cx; + +},{}],40:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule emptyFunction */ -var copyProperties = _dereq_("./copyProperties"); - function makeEmptyFunction(arg) { return function() { return arg; @@ -3164,32 +2616,23 @@ function makeEmptyFunction(arg) { */ function emptyFunction() {} -copyProperties(emptyFunction, { - thatReturns: makeEmptyFunction, - thatReturnsFalse: makeEmptyFunction(false), - thatReturnsTrue: makeEmptyFunction(true), - thatReturnsNull: makeEmptyFunction(null), - thatReturnsThis: function() { return this; }, - thatReturnsArgument: function(arg) { return arg; } -}); +emptyFunction.thatReturns = makeEmptyFunction; +emptyFunction.thatReturnsFalse = makeEmptyFunction(false); +emptyFunction.thatReturnsTrue = makeEmptyFunction(true); +emptyFunction.thatReturnsNull = makeEmptyFunction(null); +emptyFunction.thatReturnsThis = function() { return this; }; +emptyFunction.thatReturnsArgument = function(arg) { return arg; }; module.exports = emptyFunction; -},{"./copyProperties":40}],42:[function(_dereq_,module,exports){ +},{}],41:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule invariant */ @@ -3237,353 +2680,14 @@ var invariant = function(condition, format, a, b, c, d, e, f) { module.exports = invariant; -},{}],43:[function(_dereq_,module,exports){ -/** - * Copyright 2013-2014 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. - * - * @providesModule keyMirror - * @typechecks static-only - */ - -"use strict"; - -var invariant = _dereq_("./invariant"); - -/** - * Constructs an enumeration with keys equal to their value. - * - * For example: - * - * var COLORS = keyMirror({blue: null, red: null}); - * var myColor = COLORS.blue; - * var isColorValid = !!COLORS[myColor]; - * - * The last line could not be performed if the values of the generated enum were - * not equal to their keys. - * - * Input: {key1: val1, key2: val2} - * Output: {key1: key1, key2: key2} - * - * @param {object} obj - * @return {object} - */ -var keyMirror = function(obj) { - var ret = {}; - var key; - ("production" !== "production" ? invariant( - obj instanceof Object && !Array.isArray(obj), - 'keyMirror(...): Argument must be an object.' - ) : invariant(obj instanceof Object && !Array.isArray(obj))); - for (key in obj) { - if (!obj.hasOwnProperty(key)) { - continue; - } - ret[key] = key; - } - return ret; -}; - -module.exports = keyMirror; - -},{"./invariant":42}],44:[function(_dereq_,module,exports){ -/** - * Copyright 2013-2014 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. - * - * @providesModule merge - */ - -"use strict"; - -var mergeInto = _dereq_("./mergeInto"); - -/** - * Shallow merges two structures into a return value, without mutating either. - * - * @param {?object} one Optional object with properties to merge from. - * @param {?object} two Optional object with properties to merge from. - * @return {object} The shallow extension of one by two. - */ -var merge = function(one, two) { - var result = {}; - mergeInto(result, one); - mergeInto(result, two); - return result; -}; - -module.exports = merge; - -},{"./mergeInto":46}],45:[function(_dereq_,module,exports){ -/** - * Copyright 2013-2014 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. - * - * @providesModule mergeHelpers - * - * requiresPolyfills: Array.isArray - */ - -"use strict"; - -var invariant = _dereq_("./invariant"); -var keyMirror = _dereq_("./keyMirror"); - -/** - * Maximum number of levels to traverse. Will catch circular structures. - * @const - */ -var MAX_MERGE_DEPTH = 36; - -/** - * We won't worry about edge cases like new String('x') or new Boolean(true). - * Functions are considered terminals, and arrays are not. - * @param {*} o The item/object/value to test. - * @return {boolean} true iff the argument is a terminal. - */ -var isTerminal = function(o) { - return typeof o !== 'object' || o === null; -}; - -var mergeHelpers = { - - MAX_MERGE_DEPTH: MAX_MERGE_DEPTH, - - isTerminal: isTerminal, - - /** - * Converts null/undefined values into empty object. - * - * @param {?Object=} arg Argument to be normalized (nullable optional) - * @return {!Object} - */ - normalizeMergeArg: function(arg) { - return arg === undefined || arg === null ? {} : arg; - }, - - /** - * If merging Arrays, a merge strategy *must* be supplied. If not, it is - * likely the caller's fault. If this function is ever called with anything - * but `one` and `two` being `Array`s, it is the fault of the merge utilities. - * - * @param {*} one Array to merge into. - * @param {*} two Array to merge from. - */ - checkMergeArrayArgs: function(one, two) { - ("production" !== "production" ? invariant( - Array.isArray(one) && Array.isArray(two), - 'Tried to merge arrays, instead got %s and %s.', - one, - two - ) : invariant(Array.isArray(one) && Array.isArray(two))); - }, - - /** - * @param {*} one Object to merge into. - * @param {*} two Object to merge from. - */ - checkMergeObjectArgs: function(one, two) { - mergeHelpers.checkMergeObjectArg(one); - mergeHelpers.checkMergeObjectArg(two); - }, - - /** - * @param {*} arg - */ - checkMergeObjectArg: function(arg) { - ("production" !== "production" ? invariant( - !isTerminal(arg) && !Array.isArray(arg), - 'Tried to merge an object, instead got %s.', - arg - ) : invariant(!isTerminal(arg) && !Array.isArray(arg))); - }, - - /** - * @param {*} arg - */ - checkMergeIntoObjectArg: function(arg) { - ("production" !== "production" ? invariant( - (!isTerminal(arg) || typeof arg === 'function') && !Array.isArray(arg), - 'Tried to merge into an object, instead got %s.', - arg - ) : invariant((!isTerminal(arg) || typeof arg === 'function') && !Array.isArray(arg))); - }, - - /** - * Checks that a merge was not given a circular object or an object that had - * too great of depth. - * - * @param {number} Level of recursion to validate against maximum. - */ - checkMergeLevel: function(level) { - ("production" !== "production" ? invariant( - level < MAX_MERGE_DEPTH, - 'Maximum deep merge depth exceeded. You may be attempting to merge ' + - 'circular structures in an unsupported way.' - ) : invariant(level < MAX_MERGE_DEPTH)); - }, - - /** - * Checks that the supplied merge strategy is valid. - * - * @param {string} Array merge strategy. - */ - checkArrayStrategy: function(strategy) { - ("production" !== "production" ? invariant( - strategy === undefined || strategy in mergeHelpers.ArrayStrategies, - 'You must provide an array strategy to deep merge functions to ' + - 'instruct the deep merge how to resolve merging two arrays.' - ) : invariant(strategy === undefined || strategy in mergeHelpers.ArrayStrategies)); - }, - - /** - * Set of possible behaviors of merge algorithms when encountering two Arrays - * that must be merged together. - * - `clobber`: The left `Array` is ignored. - * - `indexByIndex`: The result is achieved by recursively deep merging at - * each index. (not yet supported.) - */ - ArrayStrategies: keyMirror({ - Clobber: true, - IndexByIndex: true - }) - -}; - -module.exports = mergeHelpers; - -},{"./invariant":42,"./keyMirror":43}],46:[function(_dereq_,module,exports){ +},{}],42:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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. - * - * @providesModule mergeInto - * @typechecks static-only - */ - -"use strict"; - -var mergeHelpers = _dereq_("./mergeHelpers"); - -var checkMergeObjectArg = mergeHelpers.checkMergeObjectArg; -var checkMergeIntoObjectArg = mergeHelpers.checkMergeIntoObjectArg; - -/** - * Shallow merges two structures by mutating the first parameter. - * - * @param {object|function} one Object to be merged into. - * @param {?object} two Optional object with properties to merge from. - */ -function mergeInto(one, two) { - checkMergeIntoObjectArg(one); - if (two != null) { - checkMergeObjectArg(two); - for (var key in two) { - if (!two.hasOwnProperty(key)) { - continue; - } - one[key] = two[key]; - } - } -} - -module.exports = mergeInto; - -},{"./mergeHelpers":45}],47:[function(_dereq_,module,exports){ -/** - * Copyright 2013-2014 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. - * - * @providesModule mixInto - */ - -"use strict"; - -/** - * Simply copies properties to the prototype. - */ -var mixInto = function(constructor, methodBag) { - var methodName; - for (methodName in methodBag) { - if (!methodBag.hasOwnProperty(methodName)) { - continue; - } - constructor.prototype[methodName] = methodBag[methodName]; - } -}; - -module.exports = mixInto; - -},{}],48:[function(_dereq_,module,exports){ -/** - * Copyright 2014 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 + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule warning */ @@ -3619,7 +2723,7 @@ if ("production" !== "production") { module.exports = warning; -},{"./emptyFunction":41}],49:[function(_dereq_,module,exports){ +},{"./emptyFunction":40}],43:[function(_dereq_,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ @@ -3638,7 +2742,7 @@ define(function (_dereq_) { }); })(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(_dereq_); }); -},{"./Scheduler":51,"./async":52,"./makePromise":53}],50:[function(_dereq_,module,exports){ +},{"./Scheduler":45,"./async":46,"./makePromise":47}],44:[function(_dereq_,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ @@ -3710,7 +2814,7 @@ define(function() { }); }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); })); -},{}],51:[function(_dereq_,module,exports){ +},{}],45:[function(_dereq_,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ @@ -3794,7 +2898,7 @@ define(function(_dereq_) { }); }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(_dereq_); })); -},{"./Queue":50}],52:[function(_dereq_,module,exports){ +},{"./Queue":44}],46:[function(_dereq_,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ @@ -3839,11 +2943,21 @@ define(function(_dereq_) { } else { nextTick = (function(cjsRequire) { + var vertx; try { // vert.x 1.x || 2.x - return cjsRequire('vertx').runOnLoop || cjsRequire('vertx').runOnContext; + vertx = cjsRequire('vertx'); } catch (ignore) {} + if (vertx) { + if (typeof vertx.runOnLoop === 'function') { + return vertx.runOnLoop; + } + if (typeof vertx.runOnContext === 'function') { + return vertx.runOnContext; + } + } + // capture setTimeout to avoid being caught by fake timers // used in time based tests var capturedSetTimeout = setTimeout; @@ -3857,7 +2971,7 @@ define(function(_dereq_) { }); }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(_dereq_); })); -},{}],53:[function(_dereq_,module,exports){ +},{}],47:[function(_dereq_,module,exports){ /** @license MIT License (c) copyright 2010-2014 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ @@ -3988,10 +3102,12 @@ define(function() { */ Promise.prototype.then = function(onFulfilled, onRejected) { var parent = this._handler; + var state = parent.join().state(); - if (typeof onFulfilled !== 'function' && parent.join().state() > 0) { + if ((typeof onFulfilled !== 'function' && state > 0) || + (typeof onRejected !== 'function' && state < 0)) { // Short circuit: value will not change, simply share handler - return new Promise(Handler, parent); + return new this.constructor(Handler, parent); } var p = this._beget(); @@ -4052,9 +3168,7 @@ define(function() { } if (maybeThenable(x)) { - h = isPromise(x) - ? x._handler.join() - : getHandlerUntrusted(x); + h = getHandlerMaybeThenable(x); s = h.state(); if (s === 0) { @@ -4063,6 +3177,7 @@ define(function() { results[i] = h.value; --pending; } else { + unreportRemaining(promises, i+1, h); resolver.become(h); break; } @@ -4088,6 +3203,20 @@ define(function() { } } + function unreportRemaining(promises, start, rejectedHandler) { + var i, h, x; + for(i=start; i<promises.length; ++i) { + x = promises[i]; + if(maybeThenable(x)) { + h = getHandlerMaybeThenable(x); + + if(h !== rejectedHandler) { + h.visit(h, void 0, h._unreport); + } + } + } + } + /** * Fulfill-reject competitive race. Return a promise that will settle * to the same state as the earliest input promise to settle. @@ -4136,6 +3265,16 @@ define(function() { } /** + * Get a handler for thenable x. + * NOTE: You must only call this if maybeThenable(x) == true + * @param {object|function|Promise} x + * @returns {object} handler + */ + function getHandlerMaybeThenable(x) { + return isPromise(x) ? x._handler.join() : getHandlerUntrusted(x); + } + + /** * Get a handler for potentially untrusted thenable x * @param {*} x * @returns {object} handler @@ -4630,6 +3769,6 @@ define(function() { }); }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); })); -},{}]},{},[9]) -(9) +},{}]},{},[10]) +(10) });
\ No newline at end of file diff --git a/web/src/vendor/react/JSXTransformer.js b/web/src/vendor/react/JSXTransformer.js index 9a7bf5f0..be1cae1f 100644 --- a/web/src/vendor/react/JSXTransformer.js +++ b/web/src/vendor/react/JSXTransformer.js @@ -1,7 +1,348 @@ /** - * JSXTransformer v0.11.1 + * JSXTransformer v0.12.1 */ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.JSXTransformer=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.JSXTransformer=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ +/* jshint browser: true */ +/* jslint evil: true */ + +'use strict'; + +var buffer = _dereq_('buffer'); +var transform = _dereq_('jstransform').transform; +var typesSyntax = _dereq_('jstransform/visitors/type-syntax'); +var visitors = _dereq_('./fbtransform/visitors'); + +var headEl; +var dummyAnchor; +var inlineScriptCount = 0; + +// The source-map library relies on Object.defineProperty, but IE8 doesn't +// support it fully even with es5-sham. Indeed, es5-sham's defineProperty +// throws when Object.prototype.__defineGetter__ is missing, so we skip building +// the source map in that case. +var supportsAccessors = Object.prototype.hasOwnProperty('__defineGetter__'); + +/** + * Run provided code through jstransform. + * + * @param {string} source Original source code + * @param {object?} options Options to pass to jstransform + * @return {object} object as returned from jstransform + */ +function transformReact(source, options) { + // TODO: just use react-tools + options = options || {}; + var visitorList; + if (options.harmony) { + visitorList = visitors.getAllVisitors(); + } else { + visitorList = visitors.transformVisitors.react; + } + + if (options.stripTypes) { + // Stripping types needs to happen before the other transforms + // unfortunately, due to bad interactions. For example, + // es6-rest-param-visitors conflict with stripping rest param type + // annotation + source = transform(typesSyntax.visitorList, source, options).code; + } + + return transform(visitorList, source, { + sourceMap: supportsAccessors && options.sourceMap + }); +} + +/** + * Eval provided source after transforming it. + * + * @param {string} source Original source code + * @param {object?} options Options to pass to jstransform + */ +function exec(source, options) { + return eval(transformReact(source, options).code); +} + +/** + * This method returns a nicely formated line of code pointing to the exact + * location of the error `e`. The line is limited in size so big lines of code + * are also shown in a readable way. + * + * Example: + * ... x', overflow:'scroll'}} id={} onScroll={this.scroll} class=" ... + * ^ + * + * @param {string} code The full string of code + * @param {Error} e The error being thrown + * @return {string} formatted message + * @internal + */ +function createSourceCodeErrorMessage(code, e) { + var sourceLines = code.split('\n'); + var erroneousLine = sourceLines[e.lineNumber - 1]; + + // Removes any leading indenting spaces and gets the number of + // chars indenting the `erroneousLine` + var indentation = 0; + erroneousLine = erroneousLine.replace(/^\s+/, function(leadingSpaces) { + indentation = leadingSpaces.length; + return ''; + }); + + // Defines the number of characters that are going to show + // before and after the erroneous code + var LIMIT = 30; + var errorColumn = e.column - indentation; + + if (errorColumn > LIMIT) { + erroneousLine = '... ' + erroneousLine.slice(errorColumn - LIMIT); + errorColumn = 4 + LIMIT; + } + if (erroneousLine.length - errorColumn > LIMIT) { + erroneousLine = erroneousLine.slice(0, errorColumn + LIMIT) + ' ...'; + } + var message = '\n\n' + erroneousLine + '\n'; + message += new Array(errorColumn - 1).join(' ') + '^'; + return message; +} + +/** + * Actually transform the code. + * + * @param {string} code + * @param {string?} url + * @param {object?} options + * @return {string} The transformed code. + * @internal + */ +function transformCode(code, url, options) { + try { + var transformed = transformReact(code, options); + } catch(e) { + e.message += '\n at '; + if (url) { + if ('fileName' in e) { + // We set `fileName` if it's supported by this error object and + // a `url` was provided. + // The error will correctly point to `url` in Firefox. + e.fileName = url; + } + e.message += url + ':' + e.lineNumber + ':' + e.column; + } else { + e.message += location.href; + } + e.message += createSourceCodeErrorMessage(code, e); + throw e; + } + + if (!transformed.sourceMap) { + return transformed.code; + } + + var map = transformed.sourceMap.toJSON(); + var source; + if (url == null) { + source = "Inline JSX script"; + inlineScriptCount++; + if (inlineScriptCount > 1) { + source += ' (' + inlineScriptCount + ')'; + } + } else if (dummyAnchor) { + // Firefox has problems when the sourcemap source is a proper URL with a + // protocol and hostname, so use the pathname. We could use just the + // filename, but hopefully using the full path will prevent potential + // issues where the same filename exists in multiple directories. + dummyAnchor.href = url; + source = dummyAnchor.pathname.substr(1); + } + map.sources = [source]; + map.sourcesContent = [code]; + + return ( + transformed.code + + '\n//# sourceMappingURL=data:application/json;base64,' + + buffer.Buffer(JSON.stringify(map)).toString('base64') + ); +} + + +/** + * Appends a script element at the end of the <head> with the content of code, + * after transforming it. + * + * @param {string} code The original source code + * @param {string?} url Where the code came from. null if inline + * @param {object?} options Options to pass to jstransform + * @internal + */ +function run(code, url, options) { + var scriptEl = document.createElement('script'); + scriptEl.text = transformCode(code, url, options); + headEl.appendChild(scriptEl); +} + +/** + * Load script from the provided url and pass the content to the callback. + * + * @param {string} url The location of the script src + * @param {function} callback Function to call with the content of url + * @internal + */ +function load(url, successCallback, errorCallback) { + var xhr; + xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') + : new XMLHttpRequest(); + + // async, however scripts will be executed in the order they are in the + // DOM to mirror normal script loading. + xhr.open('GET', url, true); + if ('overrideMimeType' in xhr) { + xhr.overrideMimeType('text/plain'); + } + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + if (xhr.status === 0 || xhr.status === 200) { + successCallback(xhr.responseText); + } else { + errorCallback(); + throw new Error("Could not load " + url); + } + } + }; + return xhr.send(null); +} + +/** + * Loop over provided script tags and get the content, via innerHTML if an + * inline script, or by using XHR. Transforms are applied if needed. The scripts + * are executed in the order they are found on the page. + * + * @param {array} scripts The <script> elements to load and run. + * @internal + */ +function loadScripts(scripts) { + var result = []; + var count = scripts.length; + + function check() { + var script, i; + + for (i = 0; i < count; i++) { + script = result[i]; + + if (script.loaded && !script.executed) { + script.executed = true; + run(script.content, script.url, script.options); + } else if (!script.loaded && !script.error && !script.async) { + break; + } + } + } + + scripts.forEach(function(script, i) { + var options = { + sourceMap: true + }; + if (/;harmony=true(;|$)/.test(script.type)) { + options.harmony = true + } + if (/;stripTypes=true(;|$)/.test(script.type)) { + options.stripTypes = true; + } + + // script.async is always true for non-javascript script tags + var async = script.hasAttribute('async'); + + if (script.src) { + result[i] = { + async: async, + error: false, + executed: false, + content: null, + loaded: false, + url: script.src, + options: options + }; + + load(script.src, function(content) { + result[i].loaded = true; + result[i].content = content; + check(); + }, function() { + result[i].error = true; + check(); + }); + } else { + result[i] = { + async: async, + error: false, + executed: false, + content: script.innerHTML, + loaded: true, + url: null, + options: options + }; + } + }); + + check(); +} + +/** + * Find and run all script tags with type="text/jsx". + * + * @internal + */ +function runScripts() { + var scripts = document.getElementsByTagName('script'); + + // Array.prototype.slice cannot be used on NodeList on IE8 + var jsxScripts = []; + for (var i = 0; i < scripts.length; i++) { + if (/^text\/jsx(;|$)/.test(scripts.item(i).type)) { + jsxScripts.push(scripts.item(i)); + } + } + + if (jsxScripts.length < 1) { + return; + } + + console.warn( + 'You are using the in-browser JSX transformer. Be sure to precompile ' + + 'your JSX for production - ' + + 'http://facebook.github.io/react/docs/tooling-integration.html#jsx' + ); + + loadScripts(jsxScripts); +} + +// Listen for load event if we're in a browser and then kick off finding and +// running of scripts. +if (typeof window !== "undefined" && window !== null) { + headEl = document.getElementsByTagName('head')[0]; + dummyAnchor = document.createElement('a'); + + if (window.addEventListener) { + window.addEventListener('DOMContentLoaded', runScripts, false); + } else { + window.attachEvent('onload', runScripts); + } +} + +module.exports = { + transform: transformReact, + exec: exec +}; + +},{"./fbtransform/visitors":37,"buffer":2,"jstransform":21,"jstransform/visitors/type-syntax":33}],2:[function(_dereq_,module,exports){ /*! * The buffer module from node.js, for the browser. * @@ -11,29 +352,45 @@ var base64 = _dereq_('base64-js') var ieee754 = _dereq_('ieee754') +var isArray = _dereq_('is-array') exports.Buffer = Buffer exports.SlowBuffer = Buffer exports.INSPECT_MAX_BYTES = 50 -Buffer.poolSize = 8192 +Buffer.poolSize = 8192 // not used by this implementation + +var kMaxLength = 0x3fffffff /** - * If `Buffer._useTypedArrays`: + * If `Buffer.TYPED_ARRAY_SUPPORT`: * === true Use Uint8Array implementation (fastest) - * === false Use Object implementation (compatible down to IE6) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Note: + * + * - Implementation must support adding new properties to `Uint8Array` instances. + * Firefox 4-29 lacked support, fixed in Firefox 30+. + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + * + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will + * get the Object implementation, which is slower but will work correctly. */ -Buffer._useTypedArrays = (function () { - // Detect if browser supports Typed Arrays. Supported browsers are IE 10+, Firefox 4+, - // Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. If the browser does not support adding - // properties to `Uint8Array` instances, then that's the same as no `Uint8Array` support - // because we need to be able to add all the node Buffer API methods. This is an issue - // in Firefox 4-29. Now fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=695438 +Buffer.TYPED_ARRAY_SUPPORT = (function () { try { var buf = new ArrayBuffer(0) var arr = new Uint8Array(buf) arr.foo = function () { return 42 } - return 42 === arr.foo() && - typeof arr.subarray === 'function' // Chrome 9-10 lack `subarray` + return 42 === arr.foo() && // typed array instances can be augmented + typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` + new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` } catch (e) { return false } @@ -66,14 +423,18 @@ function Buffer (subject, encoding, noZero) { subject = base64clean(subject) length = Buffer.byteLength(subject, encoding) } else if (type === 'object' && subject !== null) { // assume object is array-like - if (subject.type === 'Buffer' && Array.isArray(subject.data)) + if (subject.type === 'Buffer' && isArray(subject.data)) subject = subject.data length = +subject.length > 0 ? Math.floor(+subject.length) : 0 } else - throw new Error('First argument needs to be a number, array or string.') + throw new TypeError('must start with number, buffer, array or string') + + if (this.length > kMaxLength) + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength.toString(16) + ' bytes') var buf - if (Buffer._useTypedArrays) { + if (Buffer.TYPED_ARRAY_SUPPORT) { // Preferred: Return an augmented `Uint8Array` instance for best performance buf = Buffer._augment(new Uint8Array(length)) } else { @@ -84,7 +445,7 @@ function Buffer (subject, encoding, noZero) { } var i - if (Buffer._useTypedArrays && typeof subject.byteLength === 'number') { + if (Buffer.TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') { // Speed optimization -- use set if we're copying from a typed array buf._set(subject) } else if (isArrayish(subject)) { @@ -98,7 +459,7 @@ function Buffer (subject, encoding, noZero) { } } else if (type === 'string') { buf.write(subject, 0, encoding) - } else if (type === 'number' && !Buffer._useTypedArrays && !noZero) { + } else if (type === 'number' && !Buffer.TYPED_ARRAY_SUPPORT && !noZero) { for (i = 0; i < length; i++) { buf[i] = 0 } @@ -107,8 +468,25 @@ function Buffer (subject, encoding, noZero) { return buf } -// STATIC METHODS -// ============== +Buffer.isBuffer = function (b) { + return !!(b != null && b._isBuffer) +} + +Buffer.compare = function (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) + throw new TypeError('Arguments must be Buffers') + + var x = a.length + var y = b.length + for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {} + if (i !== len) { + x = a[i] + y = b[i] + } + if (x < y) return -1 + if (y < x) return 1 + return 0 +} Buffer.isEncoding = function (encoding) { switch (String(encoding).toLowerCase()) { @@ -129,43 +507,8 @@ Buffer.isEncoding = function (encoding) { } } -Buffer.isBuffer = function (b) { - return !!(b != null && b._isBuffer) -} - -Buffer.byteLength = function (str, encoding) { - var ret - str = str.toString() - switch (encoding || 'utf8') { - case 'hex': - ret = str.length / 2 - break - case 'utf8': - case 'utf-8': - ret = utf8ToBytes(str).length - break - case 'ascii': - case 'binary': - case 'raw': - ret = str.length - break - case 'base64': - ret = base64ToBytes(str).length - break - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - ret = str.length * 2 - break - default: - throw new Error('Unknown encoding') - } - return ret -} - Buffer.concat = function (list, totalLength) { - assert(isArray(list), 'Usage: Buffer.concat(list[, length])') + if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])') if (list.length === 0) { return new Buffer(0) @@ -191,26 +534,118 @@ Buffer.concat = function (list, totalLength) { return buf } -Buffer.compare = function (a, b) { - assert(Buffer.isBuffer(a) && Buffer.isBuffer(b), 'Arguments must be Buffers') - var x = a.length - var y = b.length - for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {} - if (i !== len) { - x = a[i] - y = b[i] +Buffer.byteLength = function (str, encoding) { + var ret + str = str + '' + switch (encoding || 'utf8') { + case 'ascii': + case 'binary': + case 'raw': + ret = str.length + break + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + ret = str.length * 2 + break + case 'hex': + ret = str.length >>> 1 + break + case 'utf8': + case 'utf-8': + ret = utf8ToBytes(str).length + break + case 'base64': + ret = base64ToBytes(str).length + break + default: + ret = str.length } - if (x < y) { - return -1 + return ret +} + +// pre-set for values that may exist in the future +Buffer.prototype.length = undefined +Buffer.prototype.parent = undefined + +// toString(encoding, start=0, end=buffer.length) +Buffer.prototype.toString = function (encoding, start, end) { + var loweredCase = false + + start = start >>> 0 + end = end === undefined || end === Infinity ? this.length : end >>> 0 + + if (!encoding) encoding = 'utf8' + if (start < 0) start = 0 + if (end > this.length) end = this.length + if (end <= start) return '' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'binary': + return binarySlice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) + throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } } - if (y < x) { - return 1 +} + +Buffer.prototype.equals = function (b) { + if(!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) + str += ' ... ' } - return 0 + return '<Buffer ' + str + '>' +} + +Buffer.prototype.compare = function (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + return Buffer.compare(this, b) +} + +// `get` will be removed in Node 0.13+ +Buffer.prototype.get = function (offset) { + console.log('.get() is deprecated. Access using array indexes instead.') + return this.readUInt8(offset) } -// BUFFER INSTANCE METHODS -// ======================= +// `set` will be removed in Node 0.13+ +Buffer.prototype.set = function (v, offset) { + console.log('.set() is deprecated. Access using array indexes instead.') + return this.writeUInt8(v, offset) +} function hexWrite (buf, string, offset, length) { offset = Number(offset) || 0 @@ -226,14 +661,14 @@ function hexWrite (buf, string, offset, length) { // must be an even number of digits var strLen = string.length - assert(strLen % 2 === 0, 'Invalid hex string') + if (strLen % 2 !== 0) throw new Error('Invalid hex string') if (length > strLen / 2) { length = strLen / 2 } for (var i = 0; i < length; i++) { var byte = parseInt(string.substr(i * 2, 2), 16) - assert(!isNaN(byte), 'Invalid hex string') + if (isNaN(byte)) throw new Error('Invalid hex string') buf[offset + i] = byte } return i @@ -315,48 +750,7 @@ Buffer.prototype.write = function (string, offset, length, encoding) { ret = utf16leWrite(this, string, offset, length) break default: - throw new Error('Unknown encoding') - } - return ret -} - -Buffer.prototype.toString = function (encoding, start, end) { - var self = this - - encoding = String(encoding || 'utf8').toLowerCase() - start = Number(start) || 0 - end = (end === undefined) ? self.length : Number(end) - - // Fastpath empty strings - if (end === start) - return '' - - var ret - switch (encoding) { - case 'hex': - ret = hexSlice(self, start, end) - break - case 'utf8': - case 'utf-8': - ret = utf8Slice(self, start, end) - break - case 'ascii': - ret = asciiSlice(self, start, end) - break - case 'binary': - ret = binarySlice(self, start, end) - break - case 'base64': - ret = base64Slice(self, start, end) - break - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - ret = utf16leSlice(self, start, end) - break - default: - throw new Error('Unknown encoding') + throw new TypeError('Unknown encoding: ' + encoding) } return ret } @@ -368,52 +762,6 @@ Buffer.prototype.toJSON = function () { } } -Buffer.prototype.equals = function (b) { - assert(Buffer.isBuffer(b), 'Argument must be a Buffer') - return Buffer.compare(this, b) === 0 -} - -Buffer.prototype.compare = function (b) { - assert(Buffer.isBuffer(b), 'Argument must be a Buffer') - return Buffer.compare(this, b) -} - -// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) -Buffer.prototype.copy = function (target, target_start, start, end) { - var source = this - - if (!start) start = 0 - if (!end && end !== 0) end = this.length - if (!target_start) target_start = 0 - - // Copy 0 bytes; we're done - if (end === start) return - if (target.length === 0 || source.length === 0) return - - // Fatal error conditions - assert(end >= start, 'sourceEnd < sourceStart') - assert(target_start >= 0 && target_start < target.length, - 'targetStart out of bounds') - assert(start >= 0 && start < source.length, 'sourceStart out of bounds') - assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds') - - // Are we oob? - if (end > this.length) - end = this.length - if (target.length - target_start < end - start) - end = target.length - target_start + start - - var len = end - start - - if (len < 100 || !Buffer._useTypedArrays) { - for (var i = 0; i < len; i++) { - target[i + target_start] = this[i + start] - } - } else { - target._set(this.subarray(start, start + len), target_start) - } -} - function base64Slice (buf, start, end) { if (start === 0 && end === buf.length) { return base64.fromByteArray(buf) @@ -499,7 +847,7 @@ Buffer.prototype.slice = function (start, end) { if (end < start) end = start - if (Buffer._useTypedArrays) { + if (Buffer.TYPED_ARRAY_SUPPORT) { return Buffer._augment(this.subarray(start, end)) } else { var sliceLen = end - start @@ -511,365 +859,275 @@ Buffer.prototype.slice = function (start, end) { } } -// `get` will be removed in Node 0.13+ -Buffer.prototype.get = function (offset) { - console.log('.get() is deprecated. Access using array indexes instead.') - return this.readUInt8(offset) -} - -// `set` will be removed in Node 0.13+ -Buffer.prototype.set = function (v, offset) { - console.log('.set() is deprecated. Access using array indexes instead.') - return this.writeUInt8(v, offset) +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) + throw new RangeError('offset is not uint') + if (offset + ext > length) + throw new RangeError('Trying to access beyond buffer length') } Buffer.prototype.readUInt8 = function (offset, noAssert) { - if (!noAssert) { - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset < this.length, 'Trying to read beyond buffer length') - } - - if (offset >= this.length) - return - + if (!noAssert) + checkOffset(offset, 1, this.length) return this[offset] } -function readUInt16 (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') - } - - var len = buf.length - if (offset >= len) - return - - var val - if (littleEndian) { - val = buf[offset] - if (offset + 1 < len) - val |= buf[offset + 1] << 8 - } else { - val = buf[offset] << 8 - if (offset + 1 < len) - val |= buf[offset + 1] - } - return val -} - Buffer.prototype.readUInt16LE = function (offset, noAssert) { - return readUInt16(this, offset, true, noAssert) + if (!noAssert) + checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) } Buffer.prototype.readUInt16BE = function (offset, noAssert) { - return readUInt16(this, offset, false, noAssert) -} - -function readUInt32 (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') - } - - var len = buf.length - if (offset >= len) - return - - var val - if (littleEndian) { - if (offset + 2 < len) - val = buf[offset + 2] << 16 - if (offset + 1 < len) - val |= buf[offset + 1] << 8 - val |= buf[offset] - if (offset + 3 < len) - val = val + (buf[offset + 3] << 24 >>> 0) - } else { - if (offset + 1 < len) - val = buf[offset + 1] << 16 - if (offset + 2 < len) - val |= buf[offset + 2] << 8 - if (offset + 3 < len) - val |= buf[offset + 3] - val = val + (buf[offset] << 24 >>> 0) - } - return val + if (!noAssert) + checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] } Buffer.prototype.readUInt32LE = function (offset, noAssert) { - return readUInt32(this, offset, true, noAssert) -} + if (!noAssert) + checkOffset(offset, 4, this.length) -Buffer.prototype.readUInt32BE = function (offset, noAssert) { - return readUInt32(this, offset, false, noAssert) + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) } -Buffer.prototype.readInt8 = function (offset, noAssert) { - if (!noAssert) { - assert(offset !== undefined && offset !== null, - 'missing offset') - assert(offset < this.length, 'Trying to read beyond buffer length') - } - - if (offset >= this.length) - return +Buffer.prototype.readUInt32BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) - var neg = this[offset] & 0x80 - if (neg) - return (0xff - this[offset] + 1) * -1 - else - return this[offset] + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) } -function readInt16 (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') - } - - var len = buf.length - if (offset >= len) - return - - var val = readUInt16(buf, offset, littleEndian, true) - var neg = val & 0x8000 - if (neg) - return (0xffff - val + 1) * -1 - else - return val +Buffer.prototype.readInt8 = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) + return (this[offset]) + return ((0xff - this[offset] + 1) * -1) } Buffer.prototype.readInt16LE = function (offset, noAssert) { - return readInt16(this, offset, true, noAssert) + if (!noAssert) + checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val } Buffer.prototype.readInt16BE = function (offset, noAssert) { - return readInt16(this, offset, false, noAssert) -} - -function readInt32 (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') - } - - var len = buf.length - if (offset >= len) - return - - var val = readUInt32(buf, offset, littleEndian, true) - var neg = val & 0x80000000 - if (neg) - return (0xffffffff - val + 1) * -1 - else - return val + if (!noAssert) + checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val } Buffer.prototype.readInt32LE = function (offset, noAssert) { - return readInt32(this, offset, true, noAssert) -} + if (!noAssert) + checkOffset(offset, 4, this.length) -Buffer.prototype.readInt32BE = function (offset, noAssert) { - return readInt32(this, offset, false, noAssert) + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) } -function readFloat (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') - } +Buffer.prototype.readInt32BE = function (offset, noAssert) { + if (!noAssert) + checkOffset(offset, 4, this.length) - return ieee754.read(buf, offset, littleEndian, 23, 4) + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) } Buffer.prototype.readFloatLE = function (offset, noAssert) { - return readFloat(this, offset, true, noAssert) + if (!noAssert) + checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) } Buffer.prototype.readFloatBE = function (offset, noAssert) { - return readFloat(this, offset, false, noAssert) -} - -function readDouble (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset + 7 < buf.length, 'Trying to read beyond buffer length') - } - - return ieee754.read(buf, offset, littleEndian, 52, 8) + if (!noAssert) + checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) } Buffer.prototype.readDoubleLE = function (offset, noAssert) { - return readDouble(this, offset, true, noAssert) + if (!noAssert) + checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) } Buffer.prototype.readDoubleBE = function (offset, noAssert) { - return readDouble(this, offset, false, noAssert) + if (!noAssert) + checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) } -Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset < this.length, 'trying to write beyond buffer length') - verifuint(value, 0xff) - } - - if (offset >= this.length) return +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') + if (value > max || value < min) throw new TypeError('value is out of bounds') + if (offset + ext > buf.length) throw new TypeError('index out of range') +} +Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 1, 0xff, 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) this[offset] = value return offset + 1 } -function writeUInt16 (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 1 < buf.length, 'trying to write beyond buffer length') - verifuint(value, 0xffff) - } - - var len = buf.length - if (offset >= len) - return - - for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) { - buf[offset + i] = - (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> - (littleEndian ? i : 1 - i) * 8 +function objectWriteUInt16 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { + buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 } - return offset + 2 } Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { - return writeUInt16(this, value, offset, true, noAssert) + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else objectWriteUInt16(this, value, offset, true) + return offset + 2 } Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { - return writeUInt16(this, value, offset, false, noAssert) + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else objectWriteUInt16(this, value, offset, false) + return offset + 2 } -function writeUInt32 (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'trying to write beyond buffer length') - verifuint(value, 0xffffffff) - } - - var len = buf.length - if (offset >= len) - return - - for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) { - buf[offset + i] = - (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff +function objectWriteUInt32 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffffffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { + buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff } - return offset + 4 } Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { - return writeUInt32(this, value, offset, true, noAssert) + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = value + } else objectWriteUInt32(this, value, offset, true) + return offset + 4 } Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { - return writeUInt32(this, value, offset, false, noAssert) + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else objectWriteUInt32(this, value, offset, false) + return offset + 4 } Buffer.prototype.writeInt8 = function (value, offset, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset < this.length, 'Trying to write beyond buffer length') - verifsint(value, 0x7f, -0x80) - } - - if (offset >= this.length) - return - - if (value >= 0) - this.writeUInt8(value, offset, noAssert) - else - this.writeUInt8(0xff + value + 1, offset, noAssert) + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 1, 0x7f, -0x80) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + if (value < 0) value = 0xff + value + 1 + this[offset] = value return offset + 1 } -function writeInt16 (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 1 < buf.length, 'Trying to write beyond buffer length') - verifsint(value, 0x7fff, -0x8000) - } - - var len = buf.length - if (offset >= len) - return - - if (value >= 0) - writeUInt16(buf, value, offset, littleEndian, noAssert) - else - writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert) - return offset + 2 -} - Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { - return writeInt16(this, value, offset, true, noAssert) + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else objectWriteUInt16(this, value, offset, true) + return offset + 2 } Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { - return writeInt16(this, value, offset, false, noAssert) + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else objectWriteUInt16(this, value, offset, false) + return offset + 2 } -function writeInt32 (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') - verifsint(value, 0x7fffffff, -0x80000000) - } - - var len = buf.length - if (offset >= len) - return - - if (value >= 0) - writeUInt32(buf, value, offset, littleEndian, noAssert) - else - writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert) +Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + } else objectWriteUInt32(this, value, offset, true) return offset + 4 } -Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { - return writeInt32(this, value, offset, true, noAssert) +Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) + checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else objectWriteUInt32(this, value, offset, false) + return offset + 4 } -Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { - return writeInt32(this, value, offset, false, noAssert) +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (value > max || value < min) throw new TypeError('value is out of bounds') + if (offset + ext > buf.length) throw new TypeError('index out of range') } function writeFloat (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') - verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38) - } - - var len = buf.length - if (offset >= len) - return - + if (!noAssert) + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) ieee754.write(buf, value, offset, littleEndian, 23, 4) return offset + 4 } @@ -883,19 +1141,8 @@ Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { } function writeDouble (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 7 < buf.length, - 'Trying to write beyond buffer length') - verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308) - } - - var len = buf.length - if (offset >= len) - return - + if (!noAssert) + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) ieee754.write(buf, value, offset, littleEndian, 52, 8) return offset + 8 } @@ -908,20 +1155,56 @@ Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { return writeDouble(this, value, offset, false, noAssert) } +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function (target, target_start, start, end) { + var source = this + + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (!target_start) target_start = 0 + + // Copy 0 bytes; we're done + if (end === start) return + if (target.length === 0 || source.length === 0) return + + // Fatal error conditions + if (end < start) throw new TypeError('sourceEnd < sourceStart') + if (target_start < 0 || target_start >= target.length) + throw new TypeError('targetStart out of bounds') + if (start < 0 || start >= source.length) throw new TypeError('sourceStart out of bounds') + if (end < 0 || end > source.length) throw new TypeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) + end = this.length + if (target.length - target_start < end - start) + end = target.length - target_start + start + + var len = end - start + + if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < len; i++) { + target[i + target_start] = this[i + start] + } + } else { + target._set(this.subarray(start, start + len), target_start) + } +} + // fill(value, start=0, end=buffer.length) Buffer.prototype.fill = function (value, start, end) { if (!value) value = 0 if (!start) start = 0 if (!end) end = this.length - assert(end >= start, 'end < start') + if (end < start) throw new TypeError('end < start') // Fill 0 bytes; we're done if (end === start) return if (this.length === 0) return - assert(start >= 0 && start < this.length, 'start out of bounds') - assert(end >= 0 && end <= this.length, 'end out of bounds') + if (start < 0 || start >= this.length) throw new TypeError('start out of bounds') + if (end < 0 || end > this.length) throw new TypeError('end out of bounds') var i if (typeof value === 'number') { @@ -939,26 +1222,13 @@ Buffer.prototype.fill = function (value, start, end) { return this } -Buffer.prototype.inspect = function () { - var out = [] - var len = this.length - for (var i = 0; i < len; i++) { - out[i] = toHex(this[i]) - if (i === exports.INSPECT_MAX_BYTES) { - out[i + 1] = '...' - break - } - } - return '<Buffer ' + out.join(' ') + '>' -} - /** * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. * Added in Node 0.12. Only available in browsers that support ArrayBuffer. */ Buffer.prototype.toArrayBuffer = function () { if (typeof Uint8Array !== 'undefined') { - if (Buffer._useTypedArrays) { + if (Buffer.TYPED_ARRAY_SUPPORT) { return (new Buffer(this)).buffer } else { var buf = new Uint8Array(this.length) @@ -968,7 +1238,7 @@ Buffer.prototype.toArrayBuffer = function () { return buf.buffer } } else { - throw new Error('Buffer.toArrayBuffer not supported in this browser') + throw new TypeError('Buffer.toArrayBuffer not supported in this browser') } } @@ -981,6 +1251,7 @@ var BP = Buffer.prototype * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods */ Buffer._augment = function (arr) { + arr.constructor = Buffer arr._isBuffer = true // save reference to original Uint8Array get/set methods before overwriting @@ -1051,12 +1322,6 @@ function stringtrim (str) { return str.replace(/^\s+|\s+$/g, '') } -function isArray (subject) { - return (Array.isArray || function (subject) { - return Object.prototype.toString.call(subject) === '[object Array]' - })(subject) -} - function isArrayish (subject) { return isArray(subject) || Buffer.isBuffer(subject) || subject && typeof subject === 'object' && @@ -1130,36 +1395,7 @@ function decodeUtf8Char (str) { } } -/* - * We have to make sure that the value is a valid integer. This means that it - * is non-negative. It has no fractional component and that it does not - * exceed the maximum allowed value. - */ -function verifuint (value, max) { - assert(typeof value === 'number', 'cannot write a non-number as a number') - assert(value >= 0, 'specified a negative value for writing an unsigned value') - assert(value <= max, 'value is larger than maximum value for type') - assert(Math.floor(value) === value, 'value has a fractional component') -} - -function verifsint (value, max, min) { - assert(typeof value === 'number', 'cannot write a non-number as a number') - assert(value <= max, 'value larger than maximum allowed value') - assert(value >= min, 'value smaller than minimum allowed value') - assert(Math.floor(value) === value, 'value has a fractional component') -} - -function verifIEEE754 (value, max, min) { - assert(typeof value === 'number', 'cannot write a non-number as a number') - assert(value <= max, 'value larger than maximum allowed value') - assert(value >= min, 'value smaller than minimum allowed value') -} - -function assert (test, message) { - if (!test) throw new Error(message || 'Failed assertion') -} - -},{"base64-js":2,"ieee754":3}],2:[function(_dereq_,module,exports){ +},{"base64-js":3,"ieee754":4,"is-array":5}],3:[function(_dereq_,module,exports){ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; ;(function (exports) { @@ -1281,7 +1517,7 @@ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; exports.fromByteArray = uint8ToBase64 }(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) -},{}],3:[function(_dereq_,module,exports){ +},{}],4:[function(_dereq_,module,exports){ exports.read = function(buffer, offset, isLE, mLen, nBytes) { var e, m, eLen = nBytes * 8 - mLen - 1, @@ -1367,7 +1603,42 @@ exports.write = function(buffer, value, offset, isLE, mLen, nBytes) { buffer[offset + i - d] |= s * 128; }; -},{}],4:[function(_dereq_,module,exports){ +},{}],5:[function(_dereq_,module,exports){ + +/** + * isArray + */ + +var isArray = Array.isArray; + +/** + * toString + */ + +var str = Object.prototype.toString; + +/** + * Whether or not the given `val` + * is an array. + * + * example: + * + * isArray([]); + * // > true + * isArray(arguments); + * // > false + * isArray(''); + * // > false + * + * @param {mixed} val + * @return {bool} + */ + +module.exports = isArray || function (val) { + return !! val && '[object Array]' == str.call(val); +}; + +},{}],6:[function(_dereq_,module,exports){ (function (process){ // Copyright Joyent, Inc. and other Node contributors. // @@ -1594,8 +1865,8 @@ var substr = 'ab'.substr(-1) === 'b' } ; -}).call(this,_dereq_("FWaASH")) -},{"FWaASH":5}],5:[function(_dereq_,module,exports){ +}).call(this,_dereq_('_process')) +},{"_process":7}],7:[function(_dereq_,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -1603,6 +1874,8 @@ var process = module.exports = {}; process.nextTick = (function () { var canSetImmediate = typeof window !== 'undefined' && window.setImmediate; + var canMutationObserver = typeof window !== 'undefined' + && window.MutationObserver; var canPost = typeof window !== 'undefined' && window.postMessage && window.addEventListener ; @@ -1611,8 +1884,29 @@ process.nextTick = (function () { return function (f) { return window.setImmediate(f) }; } + var queue = []; + + if (canMutationObserver) { + var hiddenDiv = document.createElement("div"); + var observer = new MutationObserver(function () { + var queueList = queue.slice(); + queue.length = 0; + queueList.forEach(function (fn) { + fn(); + }); + }); + + observer.observe(hiddenDiv, { attributes: true }); + + return function nextTick(fn) { + if (!queue.length) { + hiddenDiv.setAttribute('yes', 'no'); + } + queue.push(fn); + }; + } + if (canPost) { - var queue = []; window.addEventListener('message', function (ev) { var source = ev.source; if ((source === window || source === null) && ev.data === 'process-tick') { @@ -1652,7 +1946,7 @@ process.emit = noop; process.binding = function (name) { throw new Error('process.binding is not supported'); -} +}; // TODO(shtylman) process.cwd = function () { return '/' }; @@ -1660,7 +1954,35 @@ process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; -},{}],6:[function(_dereq_,module,exports){ +},{}],8:[function(_dereq_,module,exports){ +var Base62 = (function (my) { + my.chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] + + my.encode = function(i){ + if (i === 0) {return '0'} + var s = '' + while (i > 0) { + s = this.chars[i % 62] + s + i = Math.floor(i/62) + } + return s + }; + my.decode = function(a,b,c,d){ + for ( + b = c = ( + a === (/\W|_|^$/.test(a += "") || a) + ) - 1; + d = a.charCodeAt(c++); + ) + b = b * 62 + d - [, 48, 29, 87][d >> 5]; + return b + }; + + return my; +}({})); + +module.exports = Base62 +},{}],9:[function(_dereq_,module,exports){ /* Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com> Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com> @@ -1698,18 +2020,23 @@ process.chdir = function (dir) { throwError: true, generateStatement: true, peek: true, parseAssignmentExpression: true, parseBlock: true, parseClassExpression: true, parseClassDeclaration: true, parseExpression: true, +parseDeclareClass: true, parseDeclareFunction: true, +parseDeclareModule: true, parseDeclareVariable: true, parseForStatement: true, parseFunctionDeclaration: true, parseFunctionExpression: true, parseFunctionSourceElements: true, parseVariableIdentifier: true, -parseImportSpecifier: true, +parseImportSpecifier: true, parseInterface: true, parseLeftHandSideExpression: true, parseParams: true, validateParam: true, parseSpreadOrAssignmentExpression: true, -parseStatement: true, parseSourceElement: true, parseModuleBlock: true, parseConciseBody: true, +parseStatement: true, parseSourceElement: true, parseConciseBody: true, advanceXJSChild: true, isXJSIdentifierStart: true, isXJSIdentifierPart: true, scanXJSStringLiteral: true, scanXJSIdentifier: true, parseXJSAttributeValue: true, parseXJSChild: true, parseXJSElement: true, parseXJSExpressionContainer: true, parseXJSEmptyExpression: true, -parseTypeAnnotation: true, parseTypeAnnotatableIdentifier: true, -parseYieldExpression: true +parseFunctionTypeParam: true, +parsePrimaryType: true, +parseTypeAlias: true, +parseType: true, parseTypeAnnotatableIdentifier: true, parseTypeAnnotation: true, +parseYieldExpression: true, parseAwaitExpression: true */ (function (root, factory) { @@ -1788,24 +2115,32 @@ parseYieldExpression: true '<=', '<', '>', '!=', '!==']; Syntax = { + AnyTypeAnnotation: 'AnyTypeAnnotation', ArrayExpression: 'ArrayExpression', ArrayPattern: 'ArrayPattern', + ArrayTypeAnnotation: 'ArrayTypeAnnotation', ArrowFunctionExpression: 'ArrowFunctionExpression', AssignmentExpression: 'AssignmentExpression', BinaryExpression: 'BinaryExpression', BlockStatement: 'BlockStatement', + BooleanTypeAnnotation: 'BooleanTypeAnnotation', BreakStatement: 'BreakStatement', CallExpression: 'CallExpression', CatchClause: 'CatchClause', ClassBody: 'ClassBody', ClassDeclaration: 'ClassDeclaration', ClassExpression: 'ClassExpression', + ClassImplements: 'ClassImplements', ClassProperty: 'ClassProperty', ComprehensionBlock: 'ComprehensionBlock', ComprehensionExpression: 'ComprehensionExpression', ConditionalExpression: 'ConditionalExpression', ContinueStatement: 'ContinueStatement', DebuggerStatement: 'DebuggerStatement', + DeclareClass: 'DeclareClass', + DeclareFunction: 'DeclareFunction', + DeclareModule: 'DeclareModule', + DeclareVariable: 'DeclareVariable', DoWhileStatement: 'DoWhileStatement', EmptyStatement: 'EmptyStatement', ExportDeclaration: 'ExportDeclaration', @@ -1817,29 +2152,42 @@ parseYieldExpression: true ForStatement: 'ForStatement', FunctionDeclaration: 'FunctionDeclaration', FunctionExpression: 'FunctionExpression', + FunctionTypeAnnotation: 'FunctionTypeAnnotation', + FunctionTypeParam: 'FunctionTypeParam', + GenericTypeAnnotation: 'GenericTypeAnnotation', Identifier: 'Identifier', IfStatement: 'IfStatement', ImportDeclaration: 'ImportDeclaration', + ImportDefaultSpecifier: 'ImportDefaultSpecifier', + ImportNamespaceSpecifier: 'ImportNamespaceSpecifier', ImportSpecifier: 'ImportSpecifier', + InterfaceDeclaration: 'InterfaceDeclaration', + InterfaceExtends: 'InterfaceExtends', + IntersectionTypeAnnotation: 'IntersectionTypeAnnotation', LabeledStatement: 'LabeledStatement', Literal: 'Literal', LogicalExpression: 'LogicalExpression', MemberExpression: 'MemberExpression', MethodDefinition: 'MethodDefinition', - ModuleDeclaration: 'ModuleDeclaration', + ModuleSpecifier: 'ModuleSpecifier', NewExpression: 'NewExpression', + NullableTypeAnnotation: 'NullableTypeAnnotation', + NumberTypeAnnotation: 'NumberTypeAnnotation', ObjectExpression: 'ObjectExpression', ObjectPattern: 'ObjectPattern', ObjectTypeAnnotation: 'ObjectTypeAnnotation', - OptionalParameter: 'OptionalParameter', - ParametricTypeAnnotation: 'ParametricTypeAnnotation', - ParametricallyTypedIdentifier: 'ParametricallyTypedIdentifier', + ObjectTypeCallProperty: 'ObjectTypeCallProperty', + ObjectTypeIndexer: 'ObjectTypeIndexer', + ObjectTypeProperty: 'ObjectTypeProperty', Program: 'Program', Property: 'Property', + QualifiedTypeIdentifier: 'QualifiedTypeIdentifier', ReturnStatement: 'ReturnStatement', SequenceExpression: 'SequenceExpression', SpreadElement: 'SpreadElement', SpreadProperty: 'SpreadProperty', + StringLiteralTypeAnnotation: 'StringLiteralTypeAnnotation', + StringTypeAnnotation: 'StringTypeAnnotation', SwitchCase: 'SwitchCase', SwitchStatement: 'SwitchStatement', TaggedTemplateExpression: 'TaggedTemplateExpression', @@ -1847,10 +2195,15 @@ parseYieldExpression: true TemplateLiteral: 'TemplateLiteral', ThisExpression: 'ThisExpression', ThrowStatement: 'ThrowStatement', + TupleTypeAnnotation: 'TupleTypeAnnotation', TryStatement: 'TryStatement', - TypeAnnotatedIdentifier: 'TypeAnnotatedIdentifier', + TypeAlias: 'TypeAlias', TypeAnnotation: 'TypeAnnotation', + TypeofTypeAnnotation: 'TypeofTypeAnnotation', + TypeParameterDeclaration: 'TypeParameterDeclaration', + TypeParameterInstantiation: 'TypeParameterInstantiation', UnaryExpression: 'UnaryExpression', + UnionTypeAnnotation: 'UnionTypeAnnotation', UpdateExpression: 'UpdateExpression', VariableDeclaration: 'VariableDeclaration', VariableDeclarator: 'VariableDeclarator', @@ -1868,7 +2221,8 @@ parseYieldExpression: true XJSAttribute: 'XJSAttribute', XJSSpreadAttribute: 'XJSSpreadAttribute', XJSText: 'XJSText', - YieldExpression: 'YieldExpression' + YieldExpression: 'YieldExpression', + AwaitExpression: 'AwaitExpression' }; PropertyKind = { @@ -1905,7 +2259,6 @@ parseYieldExpression: true IllegalBreak: 'Illegal break statement', IllegalDuplicateClassProperty: 'Illegal duplicate property in class definition', IllegalReturn: 'Illegal return statement', - IllegalYield: 'Illegal yield expression', IllegalSpread: 'Illegal spread element', StrictModeWith: 'Strict mode code may not include a with statement', StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', @@ -1928,23 +2281,29 @@ parseYieldExpression: true StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', StrictReservedWord: 'Use of future reserved word in strict mode', - NewlineAfterModule: 'Illegal newline after module', - NoFromAfterImport: 'Missing from after import', + MissingFromClause: 'Missing from clause', + NoAsAfterImportNamespace: 'Missing as after import *', InvalidModuleSpecifier: 'Invalid module specifier', - NestedModule: 'Module declaration can not be nested', NoUnintializedConst: 'Const must be initialized', ComprehensionRequiresBlock: 'Comprehension must have at least one block', ComprehensionError: 'Comprehension Error', EachNotAllowed: 'Each is not supported', InvalidXJSAttributeValue: 'XJS value should be either an expression or a quoted XJS text', ExpectedXJSClosingTag: 'Expected corresponding XJS closing tag for %0', - AdjacentXJSElements: 'Adjacent XJS elements must be wrapped in an enclosing tag' + AdjacentXJSElements: 'Adjacent XJS elements must be wrapped in an enclosing tag', + ConfusedAboutFunctionType: 'Unexpected token =>. It looks like ' + + 'you are trying to write a function type, but you ended up ' + + 'writing a grouped type followed by an =>, which is a syntax ' + + 'error. Remember, function type parameters are named so function ' + + 'types look like (name1: type1, name2: type2) => returnType. You ' + + 'probably wrote (type1) => returnType' }; // See also tools/generate-unicode-regex.py. Regex = { NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'), - NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]') + NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'), + LeadingZeros: new RegExp('^0+(?!$)') }; // Ensure the condition is true, otherwise throw an error. @@ -2106,14 +2465,16 @@ parseYieldExpression: true } } else if (blockComment) { if (isLineTerminator(ch)) { - if (ch === 13 && source.charCodeAt(index + 1) === 10) { + if (ch === 13) { ++index; } - ++lineNumber; - ++index; - lineStart = index; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + if (ch !== 13 || source.charCodeAt(index) === 10) { + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } } } else { ch = source.charCodeAt(index++); @@ -2461,7 +2822,9 @@ parseYieldExpression: true // Other 2-character punctuators: ++ -- << >> && || - if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) { + // Don't match these tokens if we're in a type, since they never can + // occur and can mess up types like Map<string, Array<string>> + if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0) && !state.inType) { index += 2; return { type: Token.Punctuator, @@ -2769,6 +3132,7 @@ parseYieldExpression: true if (ch === '\r' && source[index] === '\n') { ++index; } + lineStart = index; } } else if (isLineTerminator(ch.charCodeAt(0))) { break; @@ -2884,12 +3248,14 @@ parseYieldExpression: true if (ch === '\r' && source[index] === '\n') { ++index; } + lineStart = index; } } else if (isLineTerminator(ch.charCodeAt(0))) { ++lineNumber; if (ch === '\r' && source[index] === '\n') { ++index; } + lineStart = index; cooked += '\n'; } else { cooked += ch; @@ -2934,7 +3300,7 @@ parseYieldExpression: true } function scanRegExp() { - var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false; + var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false, tmp; lookahead = null; skipComment(); @@ -3010,19 +3376,43 @@ parseYieldExpression: true } } + tmp = pattern; + if (flags.indexOf('u') >= 0) { + // Replace each astral symbol and every Unicode code point + // escape sequence that represents such a symbol with a single + // ASCII symbol to avoid throwing on regular expressions that + // are only valid in combination with the `/u` flag. + tmp = tmp + .replace(/\\u\{([0-9a-fA-F]{5,6})\}/g, 'x') + .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x'); + } + + // First, detect invalid regular expressions. try { - value = new RegExp(pattern, flags); + value = new RegExp(tmp); } catch (e) { throwError({}, Messages.InvalidRegExp); } - peek(); + // Return a regular expression object for this pattern-flag pair, or + // `null` in case the current environment doesn't support the flags it + // uses. + try { + value = new RegExp(pattern, flags); + } catch (exception) { + value = null; + } + peek(); if (extra.tokenize) { return { type: Token.RegularExpression, value: value, + regex: { + pattern: pattern, + flags: flags + }, lineNumber: lineNumber, lineStart: lineStart, range: [start, index] @@ -3031,6 +3421,10 @@ parseYieldExpression: true return { literal: str, value: value, + regex: { + pattern: pattern, + flags: flags + }, range: [start, index] }; } @@ -3225,6 +3619,13 @@ parseYieldExpression: true return result; } + function rewind(token) { + index = token.range[0]; + lineNumber = token.lineNumber; + lineStart = token.lineStart; + lookahead = token; + } + function markerCreate() { if (!extra.loc && !extra.range) { return undefined; @@ -3240,6 +3641,57 @@ parseYieldExpression: true return {offset: index, line: lineNumber, col: index - lineStart}; } + function processComment(node) { + var lastChild, + trailingComments, + bottomRight = extra.bottomRightStack, + last = bottomRight[bottomRight.length - 1]; + + if (node.type === Syntax.Program) { + if (node.body.length > 0) { + return; + } + } + + if (extra.trailingComments.length > 0) { + if (extra.trailingComments[0].range[0] >= node.range[1]) { + trailingComments = extra.trailingComments; + extra.trailingComments = []; + } else { + extra.trailingComments.length = 0; + } + } else { + if (last && last.trailingComments && last.trailingComments[0].range[0] >= node.range[1]) { + trailingComments = last.trailingComments; + delete last.trailingComments; + } + } + + // Eating the stack. + if (last) { + while (last && last.range[0] >= node.range[0]) { + lastChild = last; + last = bottomRight.pop(); + } + } + + if (lastChild) { + if (lastChild.leadingComments && lastChild.leadingComments[lastChild.leadingComments.length - 1].range[1] <= node.range[0]) { + node.leadingComments = lastChild.leadingComments; + delete lastChild.leadingComments; + } + } else if (extra.leadingComments.length > 0 && extra.leadingComments[extra.leadingComments.length - 1].range[1] <= node.range[0]) { + node.leadingComments = extra.leadingComments; + extra.leadingComments = []; + } + + if (trailingComments) { + node.trailingComments = trailingComments; + } + + bottomRight.push(node); + } + function markerApply(marker, node) { if (extra.range) { node.range = [marker.offset, index]; @@ -3257,6 +3709,9 @@ parseYieldExpression: true }; node = delegate.postProcess(node); } + if (extra.attachComment) { + processComment(node); + } return node; } @@ -3398,8 +3853,8 @@ parseYieldExpression: true }, createFunctionDeclaration: function (id, params, defaults, body, rest, generator, expression, - returnType, parametricType) { - return { + isAsync, returnType, typeParameters) { + var funDecl = { type: Syntax.FunctionDeclaration, id: id, params: params, @@ -3409,13 +3864,19 @@ parseYieldExpression: true generator: generator, expression: expression, returnType: returnType, - parametricType: parametricType + typeParameters: typeParameters }; + + if (isAsync) { + funDecl.async = true; + } + + return funDecl; }, createFunctionExpression: function (id, params, defaults, body, rest, generator, expression, - returnType, parametricType) { - return { + isAsync, returnType, typeParameters) { + var funExpr = { type: Syntax.FunctionExpression, id: id, params: params, @@ -3425,8 +3886,14 @@ parseYieldExpression: true generator: generator, expression: expression, returnType: returnType, - parametricType: parametricType + typeParameters: typeParameters }; + + if (isAsync) { + funExpr.async = true; + } + + return funExpr; }, createIdentifier: function (name) { @@ -3438,25 +3905,110 @@ parseYieldExpression: true // are added later (like 'loc' and 'range'). This just helps // keep the shape of Identifier nodes consistent with everything // else. - typeAnnotation: undefined + typeAnnotation: undefined, + optional: undefined }; }, - createTypeAnnotation: function (typeIdentifier, parametricType, params, returnType, nullable) { + createTypeAnnotation: function (typeAnnotation) { return { type: Syntax.TypeAnnotation, - id: typeIdentifier, - parametricType: parametricType, + typeAnnotation: typeAnnotation + }; + }, + + createFunctionTypeAnnotation: function (params, returnType, rest, typeParameters) { + return { + type: Syntax.FunctionTypeAnnotation, params: params, returnType: returnType, - nullable: nullable + rest: rest, + typeParameters: typeParameters + }; + }, + + createFunctionTypeParam: function (name, typeAnnotation, optional) { + return { + type: Syntax.FunctionTypeParam, + name: name, + typeAnnotation: typeAnnotation, + optional: optional + }; + }, + + createNullableTypeAnnotation: function (typeAnnotation) { + return { + type: Syntax.NullableTypeAnnotation, + typeAnnotation: typeAnnotation + }; + }, + + createArrayTypeAnnotation: function (elementType) { + return { + type: Syntax.ArrayTypeAnnotation, + elementType: elementType + }; + }, + + createGenericTypeAnnotation: function (id, typeParameters) { + return { + type: Syntax.GenericTypeAnnotation, + id: id, + typeParameters: typeParameters + }; + }, + + createQualifiedTypeIdentifier: function (qualification, id) { + return { + type: Syntax.QualifiedTypeIdentifier, + qualification: qualification, + id: id }; }, - createParametricTypeAnnotation: function (parametricTypes) { + createTypeParameterDeclaration: function (params) { return { - type: Syntax.ParametricTypeAnnotation, - params: parametricTypes + type: Syntax.TypeParameterDeclaration, + params: params + }; + }, + + createTypeParameterInstantiation: function (params) { + return { + type: Syntax.TypeParameterInstantiation, + params: params + }; + }, + + createAnyTypeAnnotation: function () { + return { + type: Syntax.AnyTypeAnnotation + }; + }, + + createBooleanTypeAnnotation: function () { + return { + type: Syntax.BooleanTypeAnnotation + }; + }, + + createNumberTypeAnnotation: function () { + return { + type: Syntax.NumberTypeAnnotation + }; + }, + + createStringTypeAnnotation: function () { + return { + type: Syntax.StringTypeAnnotation + }; + }, + + createStringLiteralTypeAnnotation: function (token) { + return { + type: Syntax.StringLiteralTypeAnnotation, + value: token.value, + raw: source.slice(token.range[0], token.range[1]) }; }, @@ -3466,25 +4018,117 @@ parseYieldExpression: true }; }, - createObjectTypeAnnotation: function (properties) { + createTypeofTypeAnnotation: function (argument) { + return { + type: Syntax.TypeofTypeAnnotation, + argument: argument + }; + }, + + createTupleTypeAnnotation: function (types) { + return { + type: Syntax.TupleTypeAnnotation, + types: types + }; + }, + + createObjectTypeAnnotation: function (properties, indexers, callProperties) { return { type: Syntax.ObjectTypeAnnotation, - properties: properties + properties: properties, + indexers: indexers, + callProperties: callProperties + }; + }, + + createObjectTypeIndexer: function (id, key, value, isStatic) { + return { + type: Syntax.ObjectTypeIndexer, + id: id, + key: key, + value: value, + "static": isStatic }; }, - createTypeAnnotatedIdentifier: function (identifier, annotation, isOptionalParam) { + createObjectTypeCallProperty: function (value, isStatic) { return { - type: Syntax.TypeAnnotatedIdentifier, - id: identifier, - annotation: annotation + type: Syntax.ObjectTypeCallProperty, + value: value, + "static": isStatic }; }, - createOptionalParameter: function (identifier) { + createObjectTypeProperty: function (key, value, optional, isStatic) { return { - type: Syntax.OptionalParameter, - id: identifier + type: Syntax.ObjectTypeProperty, + key: key, + value: value, + optional: optional, + "static": isStatic + }; + }, + + createUnionTypeAnnotation: function (types) { + return { + type: Syntax.UnionTypeAnnotation, + types: types + }; + }, + + createIntersectionTypeAnnotation: function (types) { + return { + type: Syntax.IntersectionTypeAnnotation, + types: types + }; + }, + + createTypeAlias: function (id, typeParameters, right) { + return { + type: Syntax.TypeAlias, + id: id, + typeParameters: typeParameters, + right: right + }; + }, + + createInterface: function (id, typeParameters, body, extended) { + return { + type: Syntax.InterfaceDeclaration, + id: id, + typeParameters: typeParameters, + body: body, + "extends": extended + }; + }, + + createInterfaceExtends: function (id, typeParameters) { + return { + type: Syntax.InterfaceExtends, + id: id, + typeParameters: typeParameters + }; + }, + + createDeclareFunction: function (id) { + return { + type: Syntax.DeclareFunction, + id: id + }; + }, + + createDeclareVariable: function (id) { + return { + type: Syntax.DeclareVariable, + id: id + }; + }, + + createDeclareModule: function (id, body) { + return { + type: Syntax.DeclareModule, + id: id, + body: body }; }, @@ -3492,7 +4136,7 @@ parseYieldExpression: true return { type: Syntax.XJSAttribute, name: name, - value: value + value: value || null }; }, @@ -3582,11 +4226,15 @@ parseYieldExpression: true }, createLiteral: function (token) { - return { + var object = { type: Syntax.Literal, value: token.value, raw: source.slice(token.range[0], token.range[1]) }; + if (token.regex) { + object.regex = token.regex; + } + return object; }, createMemberExpression: function (accessor, object, property) { @@ -3781,8 +4429,8 @@ parseYieldExpression: true }; }, - createArrowFunctionExpression: function (params, defaults, body, rest, expression) { - return { + createArrowFunctionExpression: function (params, defaults, body, rest, expression, isAsync) { + var arrowExpr = { type: Syntax.ArrowFunctionExpression, id: null, params: params, @@ -3792,6 +4440,12 @@ parseYieldExpression: true generator: false, expression: expression }; + + if (isAsync) { + arrowExpr.async = true; + } + + return arrowExpr; }, createMethodDefinition: function (propertyType, kind, key, value) { @@ -3804,10 +4458,13 @@ parseYieldExpression: true }; }, - createClassProperty: function (propertyIdentifier) { + createClassProperty: function (key, typeAnnotation, computed, isStatic) { return { type: Syntax.ClassProperty, - id: propertyIdentifier + key: key, + typeAnnotation: typeAnnotation, + computed: computed, + "static": isStatic }; }, @@ -3818,24 +4475,43 @@ parseYieldExpression: true }; }, - createClassExpression: function (id, superClass, body, parametricType) { + createClassImplements: function (id, typeParameters) { + return { + type: Syntax.ClassImplements, + id: id, + typeParameters: typeParameters + }; + }, + + createClassExpression: function (id, superClass, body, typeParameters, superTypeParameters, implemented) { return { type: Syntax.ClassExpression, id: id, superClass: superClass, body: body, - parametricType: parametricType + typeParameters: typeParameters, + superTypeParameters: superTypeParameters, + "implements": implemented }; }, - createClassDeclaration: function (id, superClass, body, parametricType, superParametricType) { + createClassDeclaration: function (id, superClass, body, typeParameters, superTypeParameters, implemented) { return { type: Syntax.ClassDeclaration, id: id, superClass: superClass, body: body, - parametricType: parametricType, - superParametricType: superParametricType + typeParameters: typeParameters, + superTypeParameters: superTypeParameters, + "implements": implemented + }; + }, + + createModuleSpecifier: function (token) { + return { + type: Syntax.ModuleSpecifier, + value: token.value, + raw: source.slice(token.range[0], token.range[1]) }; }, @@ -3853,9 +4529,24 @@ parseYieldExpression: true }; }, - createExportDeclaration: function (declaration, specifiers, source) { + createImportDefaultSpecifier: function (id) { + return { + type: Syntax.ImportDefaultSpecifier, + id: id + }; + }, + + createImportNamespaceSpecifier: function (id) { + return { + type: Syntax.ImportNamespaceSpecifier, + id: id + }; + }, + + createExportDeclaration: function (isDefault, declaration, specifiers, source) { return { type: Syntax.ExportDeclaration, + 'default': !!isDefault, declaration: declaration, specifiers: specifiers, source: source @@ -3870,11 +4561,10 @@ parseYieldExpression: true }; }, - createImportDeclaration: function (specifiers, kind, source) { + createImportDeclaration: function (specifiers, source) { return { type: Syntax.ImportDeclaration, specifiers: specifiers, - kind: kind, source: source }; }, @@ -3887,12 +4577,10 @@ parseYieldExpression: true }; }, - createModuleDeclaration: function (id, source, body) { + createAwaitExpression: function (argument) { return { - type: Syntax.ModuleDeclaration, - id: id, - source: source, - body: body + type: Syntax.AwaitExpression, + argument: argument }; }, @@ -4016,13 +4704,21 @@ parseYieldExpression: true // Expect the next token to match the specified keyword. // If not, an exception will be thrown. - function expectKeyword(keyword) { + function expectKeyword(keyword, contextual) { var token = lex(); - if (token.type !== Token.Keyword || token.value !== keyword) { + if (token.type !== (contextual ? Token.Identifier : Token.Keyword) || + token.value !== keyword) { throwUnexpected(token); } } + // Expect the next token to match the specified contextual keyword. + // If not, an exception will be thrown. + + function expectContextualKeyword(keyword) { + return expectKeyword(keyword, true); + } + // Return true if the next token matches the specified punctuator. function match(value) { @@ -4031,15 +4727,15 @@ parseYieldExpression: true // Return true if the next token matches the specified keyword - function matchKeyword(keyword) { - return lookahead.type === Token.Keyword && lookahead.value === keyword; + function matchKeyword(keyword, contextual) { + var expectedType = contextual ? Token.Identifier : Token.Keyword; + return lookahead.type === expectedType && lookahead.value === keyword; } - // Return true if the next token matches the specified contextual keyword function matchContextualKeyword(keyword) { - return lookahead.type === Token.Identifier && lookahead.value === keyword; + return matchKeyword(keyword, true); } // Return true if the next token is an assignment operator @@ -4065,8 +4761,33 @@ parseYieldExpression: true op === '|='; } + // Note that 'yield' is treated as a keyword in strict mode, but a + // contextual keyword (identifier) in non-strict mode, so we need to + // use matchKeyword('yield', false) and matchKeyword('yield', true) + // (i.e. matchContextualKeyword) appropriately. + function matchYield() { + return state.yieldAllowed && matchKeyword('yield', !strict); + } + + function matchAsync() { + var backtrackToken = lookahead, matches = false; + + if (matchContextualKeyword('async')) { + lex(); // Make sure peekLineTerminator() starts after 'async'. + matches = !peekLineTerminator(); + rewind(backtrackToken); // Revert the lex(). + } + + return matches; + } + + function matchAwait() { + return state.awaitAllowed && matchContextualKeyword('await'); + } + function consumeSemicolon() { - var line; + var line, oldIndex = index, oldLineNumber = lineNumber, + oldLineStart = lineStart, oldLookahead = lookahead; // Catch the very common case first: immediately a semicolon (char #59). if (source.charCodeAt(index) === 59) { @@ -4077,6 +4798,10 @@ parseYieldExpression: true line = lineNumber; skipComment(); if (lineNumber !== line) { + index = oldIndex; + lineNumber = oldLineNumber; + lineStart = oldLineStart; + lookahead = oldLookahead; return; } @@ -4167,12 +4892,14 @@ parseYieldExpression: true // 11.1.5 Object Initialiser function parsePropertyFunction(options) { - var previousStrict, previousYieldAllowed, params, defaults, body, - marker = markerCreate(); + var previousStrict, previousYieldAllowed, previousAwaitAllowed, + params, defaults, body, marker = markerCreate(); previousStrict = strict; previousYieldAllowed = state.yieldAllowed; state.yieldAllowed = options.generator; + previousAwaitAllowed = state.awaitAllowed; + state.awaitAllowed = options.async; params = options.params || []; defaults = options.defaults || []; @@ -4182,6 +4909,7 @@ parseYieldExpression: true } strict = previousStrict; state.yieldAllowed = previousYieldAllowed; + state.awaitAllowed = previousAwaitAllowed; return markerApply(marker, delegate.createFunctionExpression( null, @@ -4191,8 +4919,9 @@ parseYieldExpression: true options.rest || null, options.generator, body.type !== Syntax.BlockStatement, + options.async, options.returnType, - options.parametricType + options.typeParameters )); } @@ -4209,14 +4938,14 @@ parseYieldExpression: true throwErrorTolerant(tmp.stricted, tmp.message); } - method = parsePropertyFunction({ params: tmp.params, defaults: tmp.defaults, rest: tmp.rest, generator: options.generator, + async: options.async, returnType: tmp.returnType, - parametricType: options.parametricType + typeParameters: options.typeParameters }); strict = previousStrict; @@ -4256,46 +4985,138 @@ parseYieldExpression: true function parseObjectProperty() { var token, key, id, value, param, expr, computed, - marker = markerCreate(); + marker = markerCreate(), returnType; token = lookahead; computed = (token.value === '['); - if (token.type === Token.Identifier || computed) { - + if (token.type === Token.Identifier || computed || matchAsync()) { id = parseObjectPropertyKey(); + if (match(':')) { + lex(); + + return markerApply( + marker, + delegate.createProperty( + 'init', + id, + parseAssignmentExpression(), + false, + false, + computed + ) + ); + } + + if (match('(')) { + return markerApply( + marker, + delegate.createProperty( + 'init', + id, + parsePropertyMethodFunction({ + generator: false, + async: false + }), + true, + false, + computed + ) + ); + } + // Property Assignment: Getter and Setter. - if (token.value === 'get' && !(match(':') || match('('))) { + if (token.value === 'get') { computed = (lookahead.value === '['); key = parseObjectPropertyKey(); + expect('('); expect(')'); - return markerApply(marker, delegate.createProperty('get', key, parsePropertyFunction({ generator: false }), false, false, computed)); + if (match(':')) { + returnType = parseTypeAnnotation(); + } + + return markerApply( + marker, + delegate.createProperty( + 'get', + key, + parsePropertyFunction({ + generator: false, + async: false, + returnType: returnType + }), + false, + false, + computed + ) + ); } - if (token.value === 'set' && !(match(':') || match('('))) { + + if (token.value === 'set') { computed = (lookahead.value === '['); key = parseObjectPropertyKey(); + expect('('); token = lookahead; param = [ parseTypeAnnotatableIdentifier() ]; expect(')'); - return markerApply(marker, delegate.createProperty('set', key, parsePropertyFunction({ params: param, generator: false, name: token }), false, false, computed)); - } - if (match(':')) { - lex(); - return markerApply(marker, delegate.createProperty('init', id, parseAssignmentExpression(), false, false, computed)); + if (match(':')) { + returnType = parseTypeAnnotation(); + } + + return markerApply( + marker, + delegate.createProperty( + 'set', + key, + parsePropertyFunction({ + params: param, + generator: false, + async: false, + name: token, + returnType: returnType + }), + false, + false, + computed + ) + ); } - if (match('(')) { - return markerApply(marker, delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: false }), true, false, computed)); + + if (token.value === 'async') { + computed = (lookahead.value === '['); + key = parseObjectPropertyKey(); + + return markerApply( + marker, + delegate.createProperty( + 'init', + key, + parsePropertyMethodFunction({ + generator: false, + async: true + }), + true, + false, + computed + ) + ); } + if (computed) { // Computed properties can only be used with full notation. throwUnexpected(lookahead); } - return markerApply(marker, delegate.createProperty('init', id, id, false, true, false)); + + return markerApply( + marker, + delegate.createProperty('init', id, id, false, true, false) + ); } + if (token.type === Token.EOF || token.type === Token.Punctuator) { if (!match('*')) { throwUnexpected(token); @@ -4422,6 +5243,18 @@ parseYieldExpression: true return expr; } + function matchAsyncFuncExprOrDecl() { + var token; + + if (matchAsync()) { + token = lookahead2(); + if (token.type === Token.Keyword && token.value === 'function') { + return true; + } + } + + return false; + } // 11.1 Primary Expressions @@ -4998,13 +5831,15 @@ parseYieldExpression: true } function parseArrowFunctionExpression(options, marker) { - var previousStrict, previousYieldAllowed, body; + var previousStrict, previousYieldAllowed, previousAwaitAllowed, body; expect('=>'); previousStrict = strict; previousYieldAllowed = state.yieldAllowed; state.yieldAllowed = false; + previousAwaitAllowed = state.awaitAllowed; + state.awaitAllowed = !!options.async; body = parseConciseBody(); if (strict && options.firstRestricted) { @@ -5016,30 +5851,47 @@ parseYieldExpression: true strict = previousStrict; state.yieldAllowed = previousYieldAllowed; + state.awaitAllowed = previousAwaitAllowed; return markerApply(marker, delegate.createArrowFunctionExpression( options.params, options.defaults, body, options.rest, - body.type !== Syntax.BlockStatement + body.type !== Syntax.BlockStatement, + !!options.async )); } function parseAssignmentExpression() { - var marker, expr, token, params, oldParenthesizedCount; + var marker, expr, token, params, oldParenthesizedCount, + backtrackToken = lookahead, possiblyAsync = false; - // Note that 'yield' is treated as a keyword in strict mode, but a - // contextual keyword (identifier) in non-strict mode, so we need - // to use matchKeyword and matchContextualKeyword appropriately. - if ((state.yieldAllowed && matchContextualKeyword('yield')) || (strict && matchKeyword('yield'))) { + if (matchYield()) { return parseYieldExpression(); } + if (matchAwait()) { + return parseAwaitExpression(); + } + oldParenthesizedCount = state.parenthesizedCount; marker = markerCreate(); + if (matchAsyncFuncExprOrDecl()) { + return parseFunctionExpression(); + } + + if (matchAsync()) { + // We can't be completely sure that this 'async' token is + // actually a contextual keyword modifying a function + // expression, so we might have to un-lex() it later by + // calling rewind(backtrackToken). + possiblyAsync = true; + lex(); + } + if (match('(')) { token = lookahead2(); if ((token.type === Token.Punctuator && token.value === ')') || token.value === '...') { @@ -5047,11 +5899,21 @@ parseYieldExpression: true if (!match('=>')) { throwUnexpected(lex()); } + params.async = possiblyAsync; return parseArrowFunctionExpression(params, marker); } } token = lookahead; + + // If the 'async' keyword is not followed by a '(' character or an + // identifier, then it can't be an arrow function modifier, and we + // should interpret it as a normal identifer. + if (possiblyAsync && !match('(') && token.type !== Token.Identifier) { + possiblyAsync = false; + rewind(backtrackToken); + } + expr = parseConditionalExpression(); if (match('=>') && @@ -5063,10 +5925,20 @@ parseYieldExpression: true params = reinterpretAsCoverFormalsList(expr.expressions); } if (params) { + params.async = possiblyAsync; return parseArrowFunctionExpression(params, marker); } } + // If we haven't returned by now, then the 'async' keyword was not + // a function modifier, and we should rewind and interpret it as a + // normal identifier. + if (possiblyAsync) { + possiblyAsync = false; + rewind(backtrackToken); + expr = parseConditionalExpression(); + } + if (matchAssign()) { // 11.13.1 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { @@ -5172,118 +6044,446 @@ parseYieldExpression: true // 12.2 Variable Statement - function parseObjectTypeAnnotation() { - var isMethod, marker, properties = [], property, propertyKey, - propertyTypeAnnotation; + function parseTypeParameterDeclaration() { + var marker = markerCreate(), paramTypes = []; + + expect('<'); + while (!match('>')) { + paramTypes.push(parseVariableIdentifier()); + if (!match('>')) { + expect(','); + } + } + expect('>'); + + return markerApply(marker, delegate.createTypeParameterDeclaration( + paramTypes + )); + } + + function parseTypeParameterInstantiation() { + var marker = markerCreate(), oldInType = state.inType, paramTypes = []; + + state.inType = true; + + expect('<'); + while (!match('>')) { + paramTypes.push(parseType()); + if (!match('>')) { + expect(','); + } + } + expect('>'); + + state.inType = oldInType; + + return markerApply(marker, delegate.createTypeParameterInstantiation( + paramTypes + )); + } + + function parseObjectTypeIndexer(marker, isStatic) { + var id, key, value; + + expect('['); + id = parseObjectPropertyKey(); + expect(':'); + key = parseType(); + expect(']'); + expect(':'); + value = parseType(); + + return markerApply(marker, delegate.createObjectTypeIndexer( + id, + key, + value, + isStatic + )); + } + + function parseObjectTypeMethodish(marker) { + var params = [], rest = null, returnType, typeParameters = null; + if (match('<')) { + typeParameters = parseTypeParameterDeclaration(); + } + + expect('('); + while (lookahead.type === Token.Identifier) { + params.push(parseFunctionTypeParam()); + if (!match(')')) { + expect(','); + } + } + + if (match('...')) { + lex(); + rest = parseFunctionTypeParam(); + } + expect(')'); + expect(':'); + returnType = parseType(); + + return markerApply(marker, delegate.createFunctionTypeAnnotation( + params, + returnType, + rest, + typeParameters + )); + } + + function parseObjectTypeMethod(marker, isStatic, key) { + var optional = false, value; + value = parseObjectTypeMethodish(marker); + + return markerApply(marker, delegate.createObjectTypeProperty( + key, + value, + optional, + isStatic + )); + } + + function parseObjectTypeCallProperty(marker, isStatic) { + var valueMarker = markerCreate(); + return markerApply(marker, delegate.createObjectTypeCallProperty( + parseObjectTypeMethodish(valueMarker), + isStatic + )); + } + + function parseObjectType(allowStatic) { + var callProperties = [], indexers = [], marker, optional = false, + properties = [], property, propertyKey, propertyTypeAnnotation, + token, isStatic; expect('{'); while (!match('}')) { marker = markerCreate(); - propertyKey = parseObjectPropertyKey(); - isMethod = match('('); - propertyTypeAnnotation = parseTypeAnnotation(); - properties.push(markerApply(marker, delegate.createProperty( - 'init', - propertyKey, - propertyTypeAnnotation, - isMethod, - false - ))); + if (allowStatic && matchContextualKeyword('static')) { + token = lex(); + isStatic = true; + } - if (!match('}')) { - if (match(',') || match(';')) { - lex(); + if (match('[')) { + indexers.push(parseObjectTypeIndexer(marker, isStatic)); + } else if (match('(') || match('<')) { + callProperties.push(parseObjectTypeCallProperty(marker, allowStatic)); + } else { + if (isStatic && match(':')) { + propertyKey = markerApply(marker, delegate.createIdentifier(token)); + throwErrorTolerant(token, Messages.StrictReservedWord); } else { - throwUnexpected(lookahead); + propertyKey = parseObjectPropertyKey(); } + if (match('<') || match('(')) { + // This is a method property + properties.push(parseObjectTypeMethod(marker, isStatic, propertyKey)); + } else { + if (match('?')) { + lex(); + optional = true; + } + expect(':'); + propertyTypeAnnotation = parseType(); + properties.push(markerApply(marker, delegate.createObjectTypeProperty( + propertyKey, + propertyTypeAnnotation, + optional, + isStatic + ))); + } + } + + if (match(';')) { + lex(); + } else if (!match('}')) { + throwUnexpected(lookahead); } } expect('}'); - return delegate.createObjectTypeAnnotation(properties); + return delegate.createObjectTypeAnnotation( + properties, + indexers, + callProperties + ); + } + + function parseGenericType() { + var marker = markerCreate(), returnType = null, + typeParameters = null, typeIdentifier, + typeIdentifierMarker = markerCreate; + + typeIdentifier = parseVariableIdentifier(); + + while (match('.')) { + expect('.'); + typeIdentifier = markerApply(marker, delegate.createQualifiedTypeIdentifier( + typeIdentifier, + parseVariableIdentifier() + )); + } + + if (match('<')) { + typeParameters = parseTypeParameterInstantiation(); + } + + return markerApply(marker, delegate.createGenericTypeAnnotation( + typeIdentifier, + typeParameters + )); } - function parseVoidTypeAnnotation() { + function parseVoidType() { var marker = markerCreate(); expectKeyword('void'); return markerApply(marker, delegate.createVoidTypeAnnotation()); } - function parseParametricTypeAnnotation() { - var marker = markerCreate(), typeIdentifier, paramTypes = []; + function parseTypeofType() { + var argument, marker = markerCreate(); + expectKeyword('typeof'); + argument = parsePrimaryType(); + return markerApply(marker, delegate.createTypeofTypeAnnotation( + argument + )); + } - expect('<'); - while (!match('>')) { - paramTypes.push(parseVariableIdentifier()); - if (!match('>')) { - expect(','); + function parseTupleType() { + var marker = markerCreate(), types = []; + expect('['); + // We allow trailing commas + while (index < length && !match(']')) { + types.push(parseType()); + if (match(']')) { + break; } + expect(','); } - expect('>'); + expect(']'); + return markerApply(marker, delegate.createTupleTypeAnnotation( + types + )); + } - return markerApply(marker, delegate.createParametricTypeAnnotation( - paramTypes + function parseFunctionTypeParam() { + var marker = markerCreate(), name, optional = false, typeAnnotation; + name = parseVariableIdentifier(); + if (match('?')) { + lex(); + optional = true; + } + expect(':'); + typeAnnotation = parseType(); + return markerApply(marker, delegate.createFunctionTypeParam( + name, + typeAnnotation, + optional )); } - function parseTypeAnnotation(dontExpectColon) { + function parseFunctionTypeParams() { + var ret = { params: [], rest: null }; + while (lookahead.type === Token.Identifier) { + ret.params.push(parseFunctionTypeParam()); + if (!match(')')) { + expect(','); + } + } + + if (match('...')) { + lex(); + ret.rest = parseFunctionTypeParam(); + } + return ret; + } + + // The parsing of types roughly parallels the parsing of expressions, and + // primary types are kind of like primary expressions...they're the + // primitives with which other types are constructed. + function parsePrimaryType() { var typeIdentifier = null, params = null, returnType = null, - nullable = false, marker = markerCreate(), returnTypeMarker = null, - parametricType, annotation; + marker = markerCreate(), rest = null, tmp, + typeParameters, token, type, isGroupedType = false; - if (!dontExpectColon) { - expect(':'); + switch (lookahead.type) { + case Token.Identifier: + switch (lookahead.value) { + case 'any': + lex(); + return markerApply(marker, delegate.createAnyTypeAnnotation()); + case 'bool': // fallthrough + case 'boolean': + lex(); + return markerApply(marker, delegate.createBooleanTypeAnnotation()); + case 'number': + lex(); + return markerApply(marker, delegate.createNumberTypeAnnotation()); + case 'string': + lex(); + return markerApply(marker, delegate.createStringTypeAnnotation()); + } + return markerApply(marker, parseGenericType()); + case Token.Punctuator: + switch (lookahead.value) { + case '{': + return markerApply(marker, parseObjectType()); + case '[': + return parseTupleType(); + case '<': + typeParameters = parseTypeParameterDeclaration(); + expect('('); + tmp = parseFunctionTypeParams(); + params = tmp.params; + rest = tmp.rest; + expect(')'); + + expect('=>'); + + returnType = parseType(); + + return markerApply(marker, delegate.createFunctionTypeAnnotation( + params, + returnType, + rest, + typeParameters + )); + case '(': + lex(); + // Check to see if this is actually a grouped type + if (!match(')') && !match('...')) { + if (lookahead.type === Token.Identifier) { + token = lookahead2(); + isGroupedType = token.value !== '?' && token.value !== ':'; + } else { + isGroupedType = true; + } + } + + if (isGroupedType) { + type = parseType(); + expect(')'); + + // If we see a => next then someone was probably confused about + // function types, so we can provide a better error message + if (match('=>')) { + throwError({}, Messages.ConfusedAboutFunctionType); + } + + return type; + } + + tmp = parseFunctionTypeParams(); + params = tmp.params; + rest = tmp.rest; + + expect(')'); + + expect('=>'); + + returnType = parseType(); + + return markerApply(marker, delegate.createFunctionTypeAnnotation( + params, + returnType, + rest, + null /* typeParameters */ + )); + } + break; + case Token.Keyword: + switch (lookahead.value) { + case 'void': + return markerApply(marker, parseVoidType()); + case 'typeof': + return markerApply(marker, parseTypeofType()); + } + break; + case Token.StringLiteral: + token = lex(); + if (token.octal) { + throwError(token, Messages.StrictOctalLiteral); + } + return markerApply(marker, delegate.createStringLiteralTypeAnnotation( + token + )); } - if (match('{')) { - return markerApply(marker, parseObjectTypeAnnotation()); + throwUnexpected(lookahead); + } + + function parsePostfixType() { + var marker = markerCreate(), t = parsePrimaryType(); + if (match('[')) { + expect('['); + expect(']'); + return markerApply(marker, delegate.createArrayTypeAnnotation(t)); } + return t; + } + function parsePrefixType() { + var marker = markerCreate(); if (match('?')) { lex(); - nullable = true; + return markerApply(marker, delegate.createNullableTypeAnnotation( + parsePrefixType() + )); } + return parsePostfixType(); + } - if (lookahead.type === Token.Identifier) { - typeIdentifier = parseVariableIdentifier(); - if (match('<')) { - parametricType = parseParametricTypeAnnotation(); - } - } else if (match('(')) { + + function parseIntersectionType() { + var marker = markerCreate(), type, types; + type = parsePrefixType(); + types = [type]; + while (match('&')) { lex(); - params = []; - while (lookahead.type === Token.Identifier || match('?')) { - params.push(parseTypeAnnotatableIdentifier( - true, /* requireTypeAnnotation */ - true /* canBeOptionalParam */ - )); - if (!match(')')) { - expect(','); - } - } - expect(')'); + types.push(parsePrefixType()); + } - returnTypeMarker = markerCreate(); - expect('=>'); + return types.length === 1 ? + type : + markerApply(marker, delegate.createIntersectionTypeAnnotation( + types + )); + } - returnType = parseTypeAnnotation(true); - } else { - if (!matchKeyword('void')) { - throwUnexpected(lookahead); - } else { - return parseVoidTypeAnnotation(); - } + function parseUnionType() { + var marker = markerCreate(), type, types; + type = parseIntersectionType(); + types = [type]; + while (match('|')) { + lex(); + types.push(parseIntersectionType()); } + return types.length === 1 ? + type : + markerApply(marker, delegate.createUnionTypeAnnotation( + types + )); + } - return markerApply(marker, delegate.createTypeAnnotation( - typeIdentifier, - parametricType, - params, - returnType, - nullable - )); + function parseType() { + var oldInType = state.inType, type; + state.inType = true; + + type = parseUnionType(); + + state.inType = oldInType; + return type; + } + + function parseTypeAnnotation() { + var marker = markerCreate(), type; + + expect(':'); + type = parseType(); + + return markerApply(marker, delegate.createTypeAnnotation(type)); } function parseVariableIdentifier() { @@ -5308,14 +6508,13 @@ parseYieldExpression: true } if (requireTypeAnnotation || match(':')) { - ident = markerApply(marker, delegate.createTypeAnnotatedIdentifier( - ident, - parseTypeAnnotation() - )); + ident.typeAnnotation = parseTypeAnnotation(); + ident = markerApply(marker, ident); } if (isOptionalParam) { - ident = markerApply(marker, delegate.createOptionalParameter(ident)); + ident.optional = true; + ident = markerApply(marker, ident); } return ident; @@ -5324,13 +6523,22 @@ parseYieldExpression: true function parseVariableDeclaration(kind) { var id, marker = markerCreate(), - init = null; + init = null, + typeAnnotationMarker = markerCreate(); if (match('{')) { id = parseObjectInitialiser(); reinterpretAsAssignmentBindingPattern(id); + if (match(':')) { + id.typeAnnotation = parseTypeAnnotation(); + markerApply(typeAnnotationMarker, id); + } } else if (match('[')) { id = parseArrayInitialiser(); reinterpretAsAssignmentBindingPattern(id); + if (match(':')) { + id.typeAnnotation = parseTypeAnnotation(); + markerApply(typeAnnotationMarker, id); + } } else { id = state.allowKeyword ? parseNonComputedProperty() : parseTypeAnnotatableIdentifier(); // 12.2.1 @@ -5395,41 +6603,18 @@ parseYieldExpression: true return markerApply(marker, delegate.createVariableDeclaration(declarations, kind)); } - // http://wiki.ecmascript.org/doku.php?id=harmony:modules - - function parseModuleDeclaration() { - var id, src, body, marker = markerCreate(); - - lex(); // 'module' - - if (peekLineTerminator()) { - throwError({}, Messages.NewlineAfterModule); - } - - switch (lookahead.type) { + // people.mozilla.org/~jorendorff/es6-draft.html - case Token.StringLiteral: - id = parsePrimaryExpression(); - body = parseModuleBlock(); - src = null; - break; + function parseModuleSpecifier() { + var marker = markerCreate(), + specifier; - case Token.Identifier: - id = parseVariableIdentifier(); - body = null; - if (!matchContextualKeyword('from')) { - throwUnexpected(lex()); - } - lex(); - src = parsePrimaryExpression(); - if (src.type !== Syntax.Literal) { - throwError({}, Messages.InvalidModuleSpecifier); - } - break; + if (lookahead.type !== Token.StringLiteral) { + throwError({}, Messages.InvalidModuleSpecifier); } - - consumeSemicolon(); - return markerApply(marker, delegate.createModuleDeclaration(id, src, body)); + specifier = delegate.createModuleSpecifier(lookahead); + lex(); + return markerApply(marker, specifier); } function parseExportBatchSpecifier() { @@ -5439,9 +6624,14 @@ parseYieldExpression: true } function parseExportSpecifier() { - var id, name = null, marker = markerCreate(); - - id = parseVariableIdentifier(); + var id, name = null, marker = markerCreate(), from; + if (matchKeyword('default')) { + lex(); + id = markerApply(marker, delegate.createIdentifier('default')); + // export {default} from "something"; + } else { + id = parseVariableIdentifier(); + } if (matchContextualKeyword('as')) { lex(); name = parseNonComputedProperty(); @@ -5451,104 +6641,207 @@ parseYieldExpression: true } function parseExportDeclaration() { - var previousAllowKeyword, decl, def, src, specifiers, + var backtrackToken, id, previousAllowKeyword, declaration = null, + isExportFromIdentifier, + src = null, specifiers = [], marker = markerCreate(); expectKeyword('export'); + if (matchKeyword('default')) { + // covers: + // export default ... + lex(); + if (matchKeyword('function') || matchKeyword('class')) { + backtrackToken = lookahead; + lex(); + if (isIdentifierName(lookahead)) { + // covers: + // export default function foo () {} + // export default class foo {} + id = parseNonComputedProperty(); + rewind(backtrackToken); + return markerApply(marker, delegate.createExportDeclaration(true, parseSourceElement(), [id], null)); + } + // covers: + // export default function () {} + // export default class {} + rewind(backtrackToken); + switch (lookahead.value) { + case 'class': + return markerApply(marker, delegate.createExportDeclaration(true, parseClassExpression(), [], null)); + case 'function': + return markerApply(marker, delegate.createExportDeclaration(true, parseFunctionExpression(), [], null)); + } + } + + if (matchContextualKeyword('from')) { + throwError({}, Messages.UnexpectedToken, lookahead.value); + } + + // covers: + // export default {}; + // export default []; + if (match('{')) { + declaration = parseObjectInitialiser(); + } else if (match('[')) { + declaration = parseArrayInitialiser(); + } else { + declaration = parseAssignmentExpression(); + } + consumeSemicolon(); + return markerApply(marker, delegate.createExportDeclaration(true, declaration, [], null)); + } + + // non-default export if (lookahead.type === Token.Keyword) { + // covers: + // export var f = 1; switch (lookahead.value) { case 'let': case 'const': case 'var': case 'class': case 'function': - return markerApply(marker, delegate.createExportDeclaration(parseSourceElement(), null, null)); + return markerApply(marker, delegate.createExportDeclaration(false, parseSourceElement(), specifiers, null)); } } - if (isIdentifierName(lookahead)) { - previousAllowKeyword = state.allowKeyword; - state.allowKeyword = true; - decl = parseVariableDeclarationList('let'); - state.allowKeyword = previousAllowKeyword; - return markerApply(marker, delegate.createExportDeclaration(decl, null, null)); + if (match('*')) { + // covers: + // export * from "foo"; + specifiers.push(parseExportBatchSpecifier()); + + if (!matchContextualKeyword('from')) { + throwError({}, lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); + } + lex(); + src = parseModuleSpecifier(); + consumeSemicolon(); + + return markerApply(marker, delegate.createExportDeclaration(false, null, specifiers, src)); } - specifiers = []; - src = null; + expect('{'); + do { + isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default'); + specifiers.push(parseExportSpecifier()); + } while (match(',') && lex()); + expect('}'); - if (match('*')) { - specifiers.push(parseExportBatchSpecifier()); + if (matchContextualKeyword('from')) { + // covering: + // export {default} from "foo"; + // export {foo} from "foo"; + lex(); + src = parseModuleSpecifier(); + consumeSemicolon(); + } else if (isExportFromIdentifier) { + // covering: + // export {default}; // missing fromClause + throwError({}, lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); } else { - expect('{'); - do { - specifiers.push(parseExportSpecifier()); - } while (match(',') && lex()); - expect('}'); + // cover + // export {foo}; + consumeSemicolon(); } + return markerApply(marker, delegate.createExportDeclaration(false, declaration, specifiers, src)); + } - if (matchContextualKeyword('from')) { + + function parseImportSpecifier() { + // import {<foo as bar>} ...; + var id, name = null, marker = markerCreate(); + + id = parseNonComputedProperty(); + if (matchContextualKeyword('as')) { lex(); - src = parsePrimaryExpression(); - if (src.type !== Syntax.Literal) { - throwError({}, Messages.InvalidModuleSpecifier); - } + name = parseVariableIdentifier(); } - consumeSemicolon(); + return markerApply(marker, delegate.createImportSpecifier(id, name)); + } + + function parseNamedImports() { + var specifiers = []; + // {foo, bar as bas} + expect('{'); + do { + specifiers.push(parseImportSpecifier()); + } while (match(',') && lex()); + expect('}'); + return specifiers; + } + + function parseImportDefaultSpecifier() { + // import <foo> ...; + var id, marker = markerCreate(); + + id = parseNonComputedProperty(); + + return markerApply(marker, delegate.createImportDefaultSpecifier(id)); + } + + function parseImportNamespaceSpecifier() { + // import <* as foo> ...; + var id, marker = markerCreate(); + + expect('*'); + if (!matchContextualKeyword('as')) { + throwError({}, Messages.NoAsAfterImportNamespace); + } + lex(); + id = parseNonComputedProperty(); - return markerApply(marker, delegate.createExportDeclaration(null, specifiers, src)); + return markerApply(marker, delegate.createImportNamespaceSpecifier(id)); } function parseImportDeclaration() { - var specifiers, kind, src, marker = markerCreate(); + var specifiers, src, marker = markerCreate(); expectKeyword('import'); specifiers = []; - if (isIdentifierName(lookahead)) { - kind = 'default'; - specifiers.push(parseImportSpecifier()); + if (lookahead.type === Token.StringLiteral) { + // covers: + // import "foo"; + src = parseModuleSpecifier(); + consumeSemicolon(); + return markerApply(marker, delegate.createImportDeclaration(specifiers, src)); + } - if (!matchContextualKeyword('from')) { - throwError({}, Messages.NoFromAfterImport); + if (!matchKeyword('default') && isIdentifierName(lookahead)) { + // covers: + // import foo + // import foo, ... + specifiers.push(parseImportDefaultSpecifier()); + if (match(',')) { + lex(); } - lex(); + } + if (match('*')) { + // covers: + // import foo, * as foo + // import * as foo + specifiers.push(parseImportNamespaceSpecifier()); } else if (match('{')) { - kind = 'named'; - lex(); - do { - specifiers.push(parseImportSpecifier()); - } while (match(',') && lex()); - expect('}'); - - if (!matchContextualKeyword('from')) { - throwError({}, Messages.NoFromAfterImport); - } - lex(); + // covers: + // import foo, {bar} + // import {bar} + specifiers = specifiers.concat(parseNamedImports()); } - src = parsePrimaryExpression(); - if (src.type !== Syntax.Literal) { - throwError({}, Messages.InvalidModuleSpecifier); + if (!matchContextualKeyword('from')) { + throwError({}, lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); } - + lex(); + src = parseModuleSpecifier(); consumeSemicolon(); - return markerApply(marker, delegate.createImportDeclaration(specifiers, kind, src)); - } - - function parseImportSpecifier() { - var id, name = null, marker = markerCreate(); - - id = parseNonComputedProperty(); - if (matchContextualKeyword('as')) { - lex(); - name = parseVariableIdentifier(); - } - - return markerApply(marker, delegate.createImportSpecifier(id, name)); + return markerApply(marker, delegate.createImportDeclaration(specifiers, src)); } // 12.3 Empty Statement @@ -6101,6 +7394,10 @@ parseYieldExpression: true } } + if (matchAsyncFuncExprOrDecl()) { + return parseFunctionDeclaration(); + } + marker = markerCreate(); expr = parseExpression(); @@ -6226,7 +7523,7 @@ parseYieldExpression: true } function parseParam(options) { - var token, rest, param, def; + var marker, token, rest, param, def; token = lookahead; if (token.value === '...') { @@ -6235,19 +7532,31 @@ parseYieldExpression: true } if (match('[')) { + marker = markerCreate(); param = parseArrayInitialiser(); reinterpretAsDestructuredParameter(options, param); + if (match(':')) { + param.typeAnnotation = parseTypeAnnotation(); + markerApply(marker, param); + } } else if (match('{')) { + marker = markerCreate(); if (rest) { throwError({}, Messages.ObjectPatternAsRestParameter); } param = parseObjectInitialiser(); reinterpretAsDestructuredParameter(options, param); + if (match(':')) { + param.typeAnnotation = parseTypeAnnotation(); + markerApply(marker, param); + } } else { - // Typing rest params is awkward, so punting on that for now param = rest - ? parseVariableIdentifier() + ? parseTypeAnnotatableIdentifier( + false, /* requireTypeAnnotation */ + false /* canBeOptionalParam */ + ) : parseTypeAnnotatableIdentifier( false, /* requireTypeAnnotation */ true /* canBeOptionalParam */ @@ -6315,8 +7624,15 @@ parseYieldExpression: true } function parseFunctionDeclaration() { - var id, body, token, tmp, firstRestricted, message, previousStrict, previousYieldAllowed, generator, - marker = markerCreate(), parametricType; + var id, body, token, tmp, firstRestricted, message, generator, isAsync, + previousStrict, previousYieldAllowed, previousAwaitAllowed, + marker = markerCreate(), typeParameters; + + isAsync = false; + if (matchAsync()) { + lex(); + isAsync = true; + } expectKeyword('function'); @@ -6331,7 +7647,7 @@ parseYieldExpression: true id = parseVariableIdentifier(); if (match('<')) { - parametricType = parseParametricTypeAnnotation(); + typeParameters = parseTypeParameterDeclaration(); } if (strict) { @@ -6357,6 +7673,8 @@ parseYieldExpression: true previousStrict = strict; previousYieldAllowed = state.yieldAllowed; state.yieldAllowed = generator; + previousAwaitAllowed = state.awaitAllowed; + state.awaitAllowed = isAsync; body = parseFunctionSourceElements(); @@ -6368,14 +7686,35 @@ parseYieldExpression: true } strict = previousStrict; state.yieldAllowed = previousYieldAllowed; + state.awaitAllowed = previousAwaitAllowed; - return markerApply(marker, delegate.createFunctionDeclaration(id, tmp.params, tmp.defaults, body, tmp.rest, generator, false, - tmp.returnType, parametricType)); + return markerApply( + marker, + delegate.createFunctionDeclaration( + id, + tmp.params, + tmp.defaults, + body, + tmp.rest, + generator, + false, + isAsync, + tmp.returnType, + typeParameters + ) + ); } function parseFunctionExpression() { - var token, id = null, firstRestricted, message, tmp, body, previousStrict, previousYieldAllowed, generator, - marker = markerCreate(), parametricType; + var token, id = null, firstRestricted, message, tmp, body, generator, isAsync, + previousStrict, previousYieldAllowed, previousAwaitAllowed, + marker = markerCreate(), typeParameters; + + isAsync = false; + if (matchAsync()) { + lex(); + isAsync = true; + } expectKeyword('function'); @@ -6407,7 +7746,7 @@ parseYieldExpression: true } if (match('<')) { - parametricType = parseParametricTypeAnnotation(); + typeParameters = parseTypeParameterDeclaration(); } } @@ -6420,6 +7759,8 @@ parseYieldExpression: true previousStrict = strict; previousYieldAllowed = state.yieldAllowed; state.yieldAllowed = generator; + previousAwaitAllowed = state.awaitAllowed; + state.awaitAllowed = isAsync; body = parseFunctionSourceElements(); @@ -6431,20 +7772,29 @@ parseYieldExpression: true } strict = previousStrict; state.yieldAllowed = previousYieldAllowed; + state.awaitAllowed = previousAwaitAllowed; - return markerApply(marker, delegate.createFunctionExpression(id, tmp.params, tmp.defaults, body, tmp.rest, generator, false, - tmp.returnType, parametricType)); + return markerApply( + marker, + delegate.createFunctionExpression( + id, + tmp.params, + tmp.defaults, + body, + tmp.rest, + generator, + false, + isAsync, + tmp.returnType, + typeParameters + ) + ); } function parseYieldExpression() { - var yieldToken, delegateFlag, expr, marker = markerCreate(); + var delegateFlag, expr, marker = markerCreate(); - yieldToken = lex(); - assert(yieldToken.value === 'yield', 'Called parseYieldExpression with non-yield lookahead.'); - - if (!state.yieldAllowed) { - throwErrorTolerant({}, Messages.IllegalYield); - } + expectKeyword('yield', !strict); delegateFlag = false; if (match('*')) { @@ -6457,35 +7807,34 @@ parseYieldExpression: true return markerApply(marker, delegate.createYieldExpression(expr, delegateFlag)); } + function parseAwaitExpression() { + var expr, marker = markerCreate(); + expectContextualKeyword('await'); + expr = parseAssignmentExpression(); + return markerApply(marker, delegate.createAwaitExpression(expr)); + } + // 14 Classes - function parseMethodDefinition(existingPropNames) { - var token, key, param, propType, isValidDuplicateProp = false, - marker = markerCreate(), token2, parametricType, - parametricTypeMarker, annotationMarker; + function parseMethodDefinition(existingPropNames, key, isStatic, generator, computed) { + var token, param, propType, isValidDuplicateProp = false, + isAsync, typeParameters, tokenValue, returnType, + annotationMarker; - if (lookahead.value === 'static') { - propType = ClassPropertyType["static"]; - lex(); - } else { - propType = ClassPropertyType.prototype; - } + propType = isStatic ? ClassPropertyType["static"] : ClassPropertyType.prototype; - if (match('*')) { - lex(); - return markerApply(marker, delegate.createMethodDefinition( + if (generator) { + return delegate.createMethodDefinition( propType, '', - parseObjectPropertyKey(), + key, parsePropertyMethodFunction({ generator: true }) - )); + ); } - token = lookahead; - //parametricTypeMarker = markerCreate(); - key = parseObjectPropertyKey(); + tokenValue = key.type === 'Identifier' && key.name; - if (token.value === 'get' && !match('(')) { + if (tokenValue === 'get' && !match('(')) { key = parseObjectPropertyKey(); // It is a syntax error if any other properties have a name @@ -6508,14 +7857,17 @@ parseYieldExpression: true expect('('); expect(')'); - return markerApply(marker, delegate.createMethodDefinition( + if (match(':')) { + returnType = parseTypeAnnotation(); + } + return delegate.createMethodDefinition( propType, 'get', key, - parsePropertyFunction({ generator: false }) - )); + parsePropertyFunction({ generator: false, returnType: returnType }) + ); } - if (token.value === 'set' && !match('(')) { + if (tokenValue === 'set' && !match('(')) { key = parseObjectPropertyKey(); // It is a syntax error if any other properties have a name @@ -6540,16 +7892,29 @@ parseYieldExpression: true token = lookahead; param = [ parseTypeAnnotatableIdentifier() ]; expect(')'); - return markerApply(marker, delegate.createMethodDefinition( + if (match(':')) { + returnType = parseTypeAnnotation(); + } + return delegate.createMethodDefinition( propType, 'set', key, - parsePropertyFunction({ params: param, generator: false, name: token }) - )); + parsePropertyFunction({ + params: param, + generator: false, + name: token, + returnType: returnType + }) + ); } if (match('<')) { - parametricType = parseParametricTypeAnnotation(); + typeParameters = parseTypeParameterDeclaration(); + } + + isAsync = tokenValue === 'async' && !match('('); + if (isAsync) { + key = parseObjectPropertyKey(); } // It is a syntax error if any other properties have the same name as a @@ -6561,42 +7926,64 @@ parseYieldExpression: true } existingPropNames[propType][key.name].data = true; - return markerApply(marker, delegate.createMethodDefinition( + return delegate.createMethodDefinition( propType, '', key, parsePropertyMethodFunction({ generator: false, - parametricType: parametricType + async: isAsync, + typeParameters: typeParameters }) - )); + ); } - function parseClassProperty(existingPropNames) { - var marker = markerCreate(), propertyIdentifier; + function parseClassProperty(existingPropNames, key, computed, isStatic) { + var typeAnnotation; - propertyIdentifier = parseTypeAnnotatableIdentifier(); + typeAnnotation = parseTypeAnnotation(); expect(';'); - return markerApply(marker, delegate.createClassProperty( - propertyIdentifier - )); + return delegate.createClassProperty( + key, + typeAnnotation, + computed, + isStatic + ); } function parseClassElement(existingProps) { + var computed, generator = false, key, marker = markerCreate(), + isStatic = false; if (match(';')) { lex(); return; } - var doubleLookahead = lookahead2(); - if (doubleLookahead.type === Token.Punctuator) { - if (doubleLookahead.value === ':') { - return parseClassProperty(existingProps); - } + if (lookahead.value === 'static') { + lex(); + isStatic = true; + } + + if (match('*')) { + lex(); + generator = true; + } + + computed = (lookahead.value === '['); + key = parseObjectPropertyKey(); + + if (!generator && lookahead.value === ':') { + return markerApply(marker, parseClassProperty(existingProps, key, computed, isStatic)); } - return parseMethodDefinition(existingProps); + return markerApply(marker, parseMethodDefinition( + existingProps, + key, + isStatic, + generator, + computed + )); } function parseClassBody() { @@ -6623,66 +8010,109 @@ parseYieldExpression: true return markerApply(marker, delegate.createClassBody(classElements)); } + function parseClassImplements() { + var id, implemented = [], marker, typeParameters; + expectContextualKeyword('implements'); + while (index < length) { + marker = markerCreate(); + id = parseVariableIdentifier(); + if (match('<')) { + typeParameters = parseTypeParameterInstantiation(); + } else { + typeParameters = null; + } + implemented.push(markerApply(marker, delegate.createClassImplements( + id, + typeParameters + ))); + if (!match(',')) { + break; + } + expect(','); + } + return implemented; + } + function parseClassExpression() { - var id, previousYieldAllowed, superClass = null, marker = markerCreate(), - parametricType; + var id, implemented, previousYieldAllowed, superClass = null, + superTypeParameters, marker = markerCreate(), typeParameters; expectKeyword('class'); - if (!matchKeyword('extends') && !match('{')) { + if (!matchKeyword('extends') && !matchContextualKeyword('implements') && !match('{')) { id = parseVariableIdentifier(); } if (match('<')) { - parametricType = parseParametricTypeAnnotation(); + typeParameters = parseTypeParameterDeclaration(); } if (matchKeyword('extends')) { expectKeyword('extends'); previousYieldAllowed = state.yieldAllowed; state.yieldAllowed = false; - superClass = parseAssignmentExpression(); + superClass = parseLeftHandSideExpressionAllowCall(); + if (match('<')) { + superTypeParameters = parseTypeParameterInstantiation(); + } state.yieldAllowed = previousYieldAllowed; } - return markerApply(marker, delegate.createClassExpression(id, superClass, parseClassBody(), parametricType)); + if (matchContextualKeyword('implements')) { + implemented = parseClassImplements(); + } + + return markerApply(marker, delegate.createClassExpression( + id, + superClass, + parseClassBody(), + typeParameters, + superTypeParameters, + implemented + )); } function parseClassDeclaration() { - var id, previousYieldAllowed, superClass = null, marker = markerCreate(), - parametricType, superParametricType; + var id, implemented, previousYieldAllowed, superClass = null, + superTypeParameters, marker = markerCreate(), typeParameters; expectKeyword('class'); id = parseVariableIdentifier(); if (match('<')) { - parametricType = parseParametricTypeAnnotation(); + typeParameters = parseTypeParameterDeclaration(); } if (matchKeyword('extends')) { expectKeyword('extends'); previousYieldAllowed = state.yieldAllowed; state.yieldAllowed = false; - superClass = parseAssignmentExpression(); + superClass = parseLeftHandSideExpressionAllowCall(); + if (match('<')) { + superTypeParameters = parseTypeParameterInstantiation(); + } state.yieldAllowed = previousYieldAllowed; } - return markerApply(marker, delegate.createClassDeclaration(id, superClass, parseClassBody(), parametricType, superParametricType)); + if (matchContextualKeyword('implements')) { + implemented = parseClassImplements(); + } + + return markerApply(marker, delegate.createClassDeclaration( + id, + superClass, + parseClassBody(), + typeParameters, + superTypeParameters, + implemented + )); } // 15 Program - function matchModuleDeclaration() { - var id; - if (matchContextualKeyword('module')) { - id = lookahead2(); - return id.type === Token.StringLiteral || id.type === Token.Identifier; - } - return false; - } - function parseSourceElement() { + var token; if (lookahead.type === Token.Keyword) { switch (lookahead.value) { case 'const': @@ -6690,17 +8120,36 @@ parseYieldExpression: true return parseConstLetDeclaration(lookahead.value); case 'function': return parseFunctionDeclaration(); - case 'export': - return parseExportDeclaration(); - case 'import': - return parseImportDeclaration(); default: return parseStatement(); } } - if (matchModuleDeclaration()) { - throwError({}, Messages.NestedModule); + if (matchContextualKeyword('type') + && lookahead2().type === Token.Identifier) { + return parseTypeAlias(); + } + + if (matchContextualKeyword('interface') + && lookahead2().type === Token.Identifier) { + return parseInterface(); + } + + if (matchContextualKeyword('declare')) { + token = lookahead2(); + if (token.type === Token.Keyword) { + switch (token.value) { + case 'class': + return parseDeclareClass(); + case 'function': + return parseDeclareFunction(); + case 'var': + return parseDeclareVariable(); + } + } else if (token.type === Token.Identifier + && token.value === 'module') { + return parseDeclareModule(); + } } if (lookahead.type !== Token.EOF) { @@ -6718,10 +8167,6 @@ parseYieldExpression: true } } - if (matchModuleDeclaration()) { - return parseModuleDeclaration(); - } - return parseSourceElement(); } @@ -6763,40 +8208,6 @@ parseYieldExpression: true return sourceElements; } - function parseModuleElement() { - return parseSourceElement(); - } - - function parseModuleElements() { - var list = [], - statement; - - while (index < length) { - if (match('}')) { - break; - } - statement = parseModuleElement(); - if (typeof statement === 'undefined') { - break; - } - list.push(statement); - } - - return list; - } - - function parseModuleBlock() { - var block, marker = markerCreate(); - - expect('{'); - - block = parseModuleElements(); - - expect('}'); - - return markerApply(marker, delegate.createBlockStatement(block)); - } - function parseProgram() { var body, marker = markerCreate(); strict = false; @@ -6833,6 +8244,10 @@ parseYieldExpression: true comment.loc = loc; } extra.comments.push(comment); + if (extra.attachComment) { + extra.leadingComments.push(comment); + extra.trailingComments.push(comment); + } } function scanComment() { @@ -6873,17 +8288,18 @@ parseYieldExpression: true } } else if (blockComment) { if (isLineTerminator(ch.charCodeAt(0))) { - if (ch === '\r' && source[index + 1] === '\n') { + if (ch === '\r') { ++index; - comment += '\r\n'; - } else { - comment += ch; + comment += '\r'; } - ++lineNumber; - ++index; - lineStart = index; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + if (ch !== '\r' || source[index] === '\n') { + comment += source[index]; + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } } } else { ch = source[index++]; @@ -7262,7 +8678,7 @@ parseYieldExpression: true } function scanXJSEntity() { - var ch, str = '', count = 0, entity; + var ch, str = '', start = index, count = 0, code; ch = source[index]; assert(ch === '&', 'Entity must start with an ampersand'); index++; @@ -7274,14 +8690,28 @@ parseYieldExpression: true str += ch; } - if (str[0] === '#' && str[1] === 'x') { - entity = String.fromCharCode(parseInt(str.substr(2), 16)); - } else if (str[0] === '#') { - entity = String.fromCharCode(parseInt(str.substr(1), 10)); - } else { - entity = XHTMLEntities[str]; + // Well-formed entity (ending was found). + if (ch === ';') { + // Numeric entity. + if (str[0] === '#') { + if (str[1] === 'x') { + code = +('0' + str.substr(1)); + } else { + // Removing leading zeros in order to avoid treating as octal in old browsers. + code = +str.substr(1).replace(Regex.LeadingZeros, ''); + } + + if (!isNaN(code)) { + return String.fromCharCode(code); + } + } else if (XHTMLEntities[str]) { + return XHTMLEntities[str]; + } } - return entity; + + // Treat non-entity sequences as regular text. + index = start + 1; + return '&'; } function scanXJSText(stopChars) { @@ -7296,6 +8726,11 @@ parseYieldExpression: true str += scanXJSEntity(); } else { index++; + if (ch === '\r' && source[index] === '\n') { + str += ch; + ch = source[index]; + index++; + } if (isLineTerminator(ch.charCodeAt(0))) { ++lineNumber; lineStart = index; @@ -7564,7 +8999,7 @@ parseYieldExpression: true } function parseXJSElement() { - var openingElement, closingElement, children = [], origInXJSChild, origInXJSTag, marker = markerCreate(); + var openingElement, closingElement = null, children = [], origInXJSChild, origInXJSTag, marker = markerCreate(); origInXJSChild = state.inXJSChild; origInXJSTag = state.inXJSTag; @@ -7603,8 +9038,181 @@ parseYieldExpression: true return markerApply(marker, delegate.createXJSElement(openingElement, closingElement, children)); } + function parseTypeAlias() { + var id, marker = markerCreate(), typeParameters = null, right; + expectContextualKeyword('type'); + id = parseVariableIdentifier(); + if (match('<')) { + typeParameters = parseTypeParameterDeclaration(); + } + expect('='); + right = parseType(); + consumeSemicolon(); + return markerApply(marker, delegate.createTypeAlias(id, typeParameters, right)); + } + + function parseInterfaceExtends() { + var marker = markerCreate(), id, typeParameters = null; + + id = parseVariableIdentifier(); + if (match('<')) { + typeParameters = parseTypeParameterInstantiation(); + } + + return markerApply(marker, delegate.createInterfaceExtends( + id, + typeParameters + )); + } + + function parseInterfaceish(marker, allowStatic) { + var body, bodyMarker, extended = [], id, + typeParameters = null; + + id = parseVariableIdentifier(); + if (match('<')) { + typeParameters = parseTypeParameterDeclaration(); + } + + if (matchKeyword('extends')) { + expectKeyword('extends'); + + while (index < length) { + extended.push(parseInterfaceExtends()); + if (!match(',')) { + break; + } + expect(','); + } + } + + bodyMarker = markerCreate(); + body = markerApply(bodyMarker, parseObjectType(allowStatic)); + + return markerApply(marker, delegate.createInterface( + id, + typeParameters, + body, + extended + )); + } + + function parseInterface() { + var body, bodyMarker, extended = [], id, marker = markerCreate(), + typeParameters = null; + + expectContextualKeyword('interface'); + return parseInterfaceish(marker, /* allowStatic */false); + } + + function parseDeclareClass() { + var marker = markerCreate(), ret; + expectContextualKeyword('declare'); + expectKeyword('class'); + + ret = parseInterfaceish(marker, /* allowStatic */true); + ret.type = Syntax.DeclareClass; + return ret; + } + + function parseDeclareFunction() { + var id, idMarker, + marker = markerCreate(), params, returnType, rest, tmp, + typeParameters = null, value, valueMarker; + + expectContextualKeyword('declare'); + expectKeyword('function'); + idMarker = markerCreate(); + id = parseVariableIdentifier(); + + valueMarker = markerCreate(); + if (match('<')) { + typeParameters = parseTypeParameterDeclaration(); + } + expect('('); + tmp = parseFunctionTypeParams(); + params = tmp.params; + rest = tmp.rest; + expect(')'); + + expect(':'); + returnType = parseType(); + + value = markerApply(valueMarker, delegate.createFunctionTypeAnnotation( + params, + returnType, + rest, + typeParameters + )); + + id.typeAnnotation = markerApply(valueMarker, delegate.createTypeAnnotation( + value + )); + markerApply(idMarker, id); + + consumeSemicolon(); + + return markerApply(marker, delegate.createDeclareFunction( + id + )); + } + + function parseDeclareVariable() { + var id, marker = markerCreate(); + expectContextualKeyword('declare'); + expectKeyword('var'); + id = parseTypeAnnotatableIdentifier(); + + consumeSemicolon(); + + return markerApply(marker, delegate.createDeclareVariable( + id + )); + } + + function parseDeclareModule() { + var body = [], bodyMarker, id, idMarker, marker = markerCreate(), token; + expectContextualKeyword('declare'); + expectContextualKeyword('module'); + + if (lookahead.type === Token.StringLiteral) { + if (strict && lookahead.octal) { + throwErrorTolerant(lookahead, Messages.StrictOctalLiteral); + } + idMarker = markerCreate(); + id = markerApply(idMarker, delegate.createLiteral(lex())); + } else { + id = parseVariableIdentifier(); + } + + bodyMarker = markerCreate(); + expect('{'); + while (index < length && !match('}')) { + token = lookahead2(); + switch (token.value) { + case 'class': + body.push(parseDeclareClass()); + break; + case 'function': + body.push(parseDeclareFunction()); + break; + case 'var': + body.push(parseDeclareVariable()); + break; + default: + throwUnexpected(lookahead); + } + } + expect('}'); + + return markerApply(marker, delegate.createDeclareModule( + id, + markerApply(bodyMarker, delegate.createBlockStatement(body)) + )); + } + function collectToken() { - var start, loc, token, range, value; + var start, loc, token, range, value, entry; if (!state.inXJSChild) { skipComment(); @@ -7627,12 +9235,19 @@ parseYieldExpression: true if (token.type !== Token.EOF) { range = [token.range[0], token.range[1]]; value = source.slice(token.range[0], token.range[1]); - extra.tokens.push({ + entry = { type: TokenName[token.type], value: value, range: range, loc: loc - }); + }; + if (token.regex) { + entry.regex = { + pattern: token.regex.pattern, + flags: token.regex.flags + }; + } + extra.tokens.push(entry); } return token; @@ -7671,6 +9286,7 @@ parseYieldExpression: true extra.tokens.push({ type: 'RegularExpression', value: regex.literal, + regex: regex.regex, range: [pos, index], loc: loc }); @@ -7688,6 +9304,12 @@ parseYieldExpression: true type: entry.type, value: entry.value }; + if (entry.regex) { + token.regex = { + pattern: entry.regex.pattern, + flags: entry.regex.flags + }; + } if (extra.range) { token.range = entry.range; } @@ -7874,14 +9496,17 @@ parseYieldExpression: true inSwitch: false, inXJSChild: false, inXJSTag: false, + inType: false, lastCommentStart: -1, - yieldAllowed: false + yieldAllowed: false, + awaitAllowed: false }; extra = {}; if (typeof options !== 'undefined') { extra.range = (typeof options.range === 'boolean') && options.range; extra.loc = (typeof options.loc === 'boolean') && options.loc; + extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment; if (extra.loc && options.source !== null && options.source !== undefined) { delegate = extend(delegate, { @@ -7901,6 +9526,13 @@ parseYieldExpression: true if (typeof options.tolerant === 'boolean' && options.tolerant) { extra.errors = []; } + if (extra.attachComment) { + extra.range = true; + extra.comments = []; + extra.bottomRightStack = []; + extra.trailingComments = []; + extra.leadingComments = []; + } } if (length > 0) { @@ -7938,7 +9570,7 @@ parseYieldExpression: true } // Sync with *.json manifests. - exports.version = '4001.3001.0000-dev-harmony-fb'; + exports.version = '8001.1001.0-dev-harmony-fb'; exports.tokenize = tokenize; @@ -7968,35 +9600,7 @@ parseYieldExpression: true })); /* vim: set sw=4 ts=4 et tw=80 : */ -},{}],7:[function(_dereq_,module,exports){ -var Base62 = (function (my) { - my.chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] - - my.encode = function(i){ - if (i === 0) {return '0'} - var s = '' - while (i > 0) { - s = this.chars[i % 62] + s - i = Math.floor(i/62) - } - return s - }; - my.decode = function(a,b,c,d){ - for ( - b = c = ( - a === (/\W|_|^$/.test(a += "") || a) - ) - 1; - d = a.charCodeAt(c++); - ) - b = b * 62 + d - [, 48, 29, 87][d >> 5]; - return b - }; - - return my; -}({})); - -module.exports = Base62 -},{}],8:[function(_dereq_,module,exports){ +},{}],10:[function(_dereq_,module,exports){ /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: @@ -8006,7 +9610,7 @@ exports.SourceMapGenerator = _dereq_('./source-map/source-map-generator').Source exports.SourceMapConsumer = _dereq_('./source-map/source-map-consumer').SourceMapConsumer; exports.SourceNode = _dereq_('./source-map/source-node').SourceNode; -},{"./source-map/source-map-consumer":13,"./source-map/source-map-generator":14,"./source-map/source-node":15}],9:[function(_dereq_,module,exports){ +},{"./source-map/source-map-consumer":15,"./source-map/source-map-generator":16,"./source-map/source-node":17}],11:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -8105,7 +9709,7 @@ define(function (_dereq_, exports, module) { }); -},{"./util":16,"amdefine":17}],10:[function(_dereq_,module,exports){ +},{"./util":18,"amdefine":19}],12:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -8251,7 +9855,7 @@ define(function (_dereq_, exports, module) { }); -},{"./base64":11,"amdefine":17}],11:[function(_dereq_,module,exports){ +},{"./base64":13,"amdefine":19}],13:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -8295,7 +9899,7 @@ define(function (_dereq_, exports, module) { }); -},{"amdefine":17}],12:[function(_dereq_,module,exports){ +},{"amdefine":19}],14:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -8378,7 +9982,7 @@ define(function (_dereq_, exports, module) { }); -},{"amdefine":17}],13:[function(_dereq_,module,exports){ +},{"amdefine":19}],15:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -8857,7 +10461,7 @@ define(function (_dereq_, exports, module) { }); -},{"./array-set":9,"./base64-vlq":10,"./binary-search":12,"./util":16,"amdefine":17}],14:[function(_dereq_,module,exports){ +},{"./array-set":11,"./base64-vlq":12,"./binary-search":14,"./util":18,"amdefine":19}],16:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -9239,7 +10843,7 @@ define(function (_dereq_, exports, module) { }); -},{"./array-set":9,"./base64-vlq":10,"./util":16,"amdefine":17}],15:[function(_dereq_,module,exports){ +},{"./array-set":11,"./base64-vlq":12,"./util":18,"amdefine":19}],17:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -9612,7 +11216,7 @@ define(function (_dereq_, exports, module) { }); -},{"./source-map-generator":14,"./util":16,"amdefine":17}],16:[function(_dereq_,module,exports){ +},{"./source-map-generator":16,"./util":18,"amdefine":19}],18:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -9819,7 +11423,7 @@ define(function (_dereq_, exports, module) { }); -},{"amdefine":17}],17:[function(_dereq_,module,exports){ +},{"amdefine":19}],19:[function(_dereq_,module,exports){ (function (process,__filename){ /** vim: et:ts=4:sw=4:sts=4 * @license amdefine 0.1.0 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. @@ -10121,8 +11725,8 @@ function amdefine(module, requireFn) { module.exports = amdefine; -}).call(this,_dereq_("FWaASH"),"/../node_modules/jstransform/node_modules/source-map/node_modules/amdefine/amdefine.js") -},{"FWaASH":5,"path":4}],18:[function(_dereq_,module,exports){ +}).call(this,_dereq_('_process'),"/node_modules/jstransform/node_modules/source-map/node_modules/amdefine/amdefine.js") +},{"_process":7,"path":6}],20:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -10210,7 +11814,7 @@ exports.extract = extract; exports.parse = parse; exports.parseAsObject = parseAsObject; -},{}],19:[function(_dereq_,module,exports){ +},{}],21:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -10268,7 +11872,6 @@ function _nodeIsBlockScopeBoundary(node, parentNode) { /** * @param {object} node - * @param {function} visitor * @param {array} path * @param {object} state */ @@ -10464,8 +12067,9 @@ function transform(visitors, source, options) { } exports.transform = transform; +exports.Syntax = Syntax; -},{"./utils":20,"esprima-fb":6,"source-map":8}],20:[function(_dereq_,module,exports){ +},{"./utils":22,"esprima-fb":9,"source-map":10}],22:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -10916,8 +12520,8 @@ function initScopeMetadata(boundaryNode, path, node) { function declareIdentInLocalScope(identName, metaData, state) { state.localScope.identifiers[identName] = { boundaryNode: metaData.boundaryNode, - path: metaData.path, - node: metaData.node, + path: metaData.bindingPath, + node: metaData.bindingNode, state: Object.create(state) }; } @@ -10934,7 +12538,6 @@ function getLexicalBindingMetadata(identName, state) { * @param {function} analyzer * @param {function} traverser * @param {object} node - * @param {function} visitor * @param {array} path * @param {object} state */ @@ -11011,16 +12614,22 @@ function enqueueNodeWithStartIndex(queue, node) { * @param {string} type - node type to lookup. */ function containsChildOfType(node, type) { + return containsChildMatching(node, function(node) { + return node.type === type; + }); +} + +function containsChildMatching(node, matcher) { var foundMatchingChild = false; function nodeTypeAnalyzer(node) { - if (node.type === type) { + if (matcher(node) === true) { foundMatchingChild = true; return false; } } function nodeTypeTraverser(child, path, state) { if (!foundMatchingChild) { - foundMatchingChild = containsChildOfType(child, type); + foundMatchingChild = containsChildMatching(child, matcher); } } analyzeAndTraverse( @@ -11049,11 +12658,20 @@ function getBoundaryNode(path) { ); } +function getTempVar(tempVarIndex) { + return '$__' + tempVarIndex; +} + +function getTempVarWithValue(tempVarIndex, tempVarValue) { + return getTempVar(tempVarIndex) + '=' + tempVarValue; +} + exports.append = append; exports.catchup = catchup; exports.catchupWhiteOut = catchupWhiteOut; exports.catchupWhiteSpace = catchupWhiteSpace; exports.catchupNewlines = catchupNewlines; +exports.containsChildMatching = containsChildMatching; exports.containsChildOfType = containsChildOfType; exports.createState = createState; exports.declareIdentInLocalScope = declareIdentInLocalScope; @@ -11071,8 +12689,10 @@ exports.updateState = updateState; exports.analyzeAndTraverse = analyzeAndTraverse; exports.getOrderedChildren = getOrderedChildren; exports.getNodeSourceText = getNodeSourceText; +exports.getTempVar = getTempVar; +exports.getTempVarWithValue = getTempVarWithValue; -},{"./docblock":18,"esprima-fb":6}],21:[function(_dereq_,module,exports){ +},{"./docblock":20,"esprima-fb":9}],23:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -11147,7 +12767,14 @@ function visitArrowFunction(traverse, node, path, state) { // Bind the function only if `this` value is used // inside it or inside any sub-expression. - if (utils.containsChildOfType(node.body, Syntax.ThisExpression)) { + var containsBindingSyntax = + utils.containsChildMatching(node.body, function(node) { + return node.type === Syntax.ThisExpression + || (node.type === Syntax.Identifier + && node.name === "super"); + }); + + if (containsBindingSyntax) { utils.append('.bind(this)', state); } @@ -11188,7 +12815,7 @@ function renderExpressionBody(traverse, node, path, state) { // Special handling of rest param. if (node.rest) { utils.append( - restParamVisitors.renderRestParamSetup(node), + restParamVisitors.renderRestParamSetup(node, state), state ); } @@ -11225,7 +12852,7 @@ exports.visitorList = [ ]; -},{"../src/utils":20,"./es6-destructuring-visitors":23,"./es6-rest-param-visitors":26,"esprima-fb":6}],22:[function(_dereq_,module,exports){ +},{"../src/utils":22,"./es6-destructuring-visitors":25,"./es6-rest-param-visitors":28,"esprima-fb":9}],24:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -11252,6 +12879,7 @@ exports.visitorList = [ var base62 = _dereq_('base62'); var Syntax = _dereq_('esprima-fb').Syntax; var utils = _dereq_('../src/utils'); +var reservedWordsHelper = _dereq_('./reserved-words-helper'); var declareIdentInLocalScope = utils.declareIdentInLocalScope; var initScopeMetadata = utils.initScopeMetadata; @@ -11370,7 +12998,7 @@ function _shouldMungeIdentifier(node, state) { * @param {object} state */ function visitClassMethod(traverse, node, path, state) { - if (node.kind === 'get' || node.kind === 'set') { + if (!state.g.opts.es5 && (node.kind === 'get' || node.kind === 'set')) { throw new Error( 'This transform does not support ' + node.kind + 'ter methods for ES6 ' + 'classes. (line: ' + node.loc.start.line + ', col: ' + @@ -11398,6 +13026,8 @@ visitClassMethod.test = function(node, path, state) { */ function visitClassFunctionExpression(traverse, node, path, state) { var methodNode = path[0]; + var isGetter = methodNode.kind === 'get'; + var isSetter = methodNode.kind === 'set'; state = utils.updateState(state, { methodFuncNode: node @@ -11408,6 +13038,7 @@ function visitClassFunctionExpression(traverse, node, path, state) { } else { var methodAccessor; var prototypeOrStatic = methodNode["static"] ? '' : '.prototype'; + var objectAccessor = state.className + prototypeOrStatic; if (methodNode.key.type === Syntax.Identifier) { // foo() {} @@ -11415,24 +13046,44 @@ function visitClassFunctionExpression(traverse, node, path, state) { if (_shouldMungeIdentifier(methodNode.key, state)) { methodAccessor = _getMungedName(methodAccessor, state); } - methodAccessor = '.' + methodAccessor; + if (isGetter || isSetter) { + methodAccessor = JSON.stringify(methodAccessor); + } else if (reservedWordsHelper.isReservedWord(methodAccessor)) { + methodAccessor = '[' + JSON.stringify(methodAccessor) + ']'; + } else { + methodAccessor = '.' + methodAccessor; + } } else if (methodNode.key.type === Syntax.Literal) { - // 'foo bar'() {} - methodAccessor = '[' + JSON.stringify(methodNode.key.value) + ']'; + // 'foo bar'() {} | get 'foo bar'() {} | set 'foo bar'() {} + methodAccessor = JSON.stringify(methodNode.key.value); + if (!(isGetter || isSetter)) { + methodAccessor = '[' + methodAccessor + ']'; + } } - utils.append( - state.className + prototypeOrStatic + - methodAccessor + '=function', - state - ); + if (isSetter || isGetter) { + utils.append( + 'Object.defineProperty(' + + objectAccessor + ',' + + methodAccessor + ',' + + '{enumerable:true,configurable:true,' + + methodNode.kind + ':function', + state + ); + } else { + utils.append( + objectAccessor + + methodAccessor + '=function' + (node.generator ? '*' : ''), + state + ); + } } utils.move(methodNode.key.range[1], state); utils.append('(', state); var params = node.params; if (params.length > 0) { - utils.move(params[0].range[0], state); + utils.catchupNewlines(params[0].range[0], state); for (var i = 0; i < params.length; i++) { utils.catchup(node.params[i].range[0], state); path.unshift(node); @@ -11457,6 +13108,9 @@ function visitClassFunctionExpression(traverse, node, path, state) { utils.catchup(node.body.range[1], state); if (methodNode.key.name !== 'constructor') { + if (isGetter || isSetter) { + utils.append('})', state); + } utils.append(';', state); } return false; @@ -11767,7 +13421,7 @@ exports.visitorList = [ visitSuperMemberExpression ]; -},{"../src/utils":20,"base62":7,"esprima-fb":6}],23:[function(_dereq_,module,exports){ +},{"../src/utils":22,"./reserved-words-helper":32,"base62":8,"esprima-fb":9}],25:[function(_dereq_,module,exports){ /** * Copyright 2014 Facebook, Inc. * @@ -11810,7 +13464,9 @@ exports.visitorList = [ var Syntax = _dereq_('esprima-fb').Syntax; var utils = _dereq_('../src/utils'); +var reservedWordsHelper = _dereq_('./reserved-words-helper'); var restParamVisitors = _dereq_('./es6-rest-param-visitors'); +var restPropertyHelpers = _dereq_('./es7-rest-property-helpers'); // ------------------------------------------------------- // 1. Structured variable declarations. @@ -11821,7 +13477,7 @@ var restParamVisitors = _dereq_('./es6-rest-param-visitors'); function visitStructuredVariable(traverse, node, path, state) { // Allocate new temp for the pattern. - utils.append(getTmpVar(state.localScope.tempVarIndex) + '=', state); + utils.append(utils.getTempVar(state.localScope.tempVarIndex) + '=', state); // Skip the pattern and assign the init to the temp. utils.catchupWhiteSpace(node.init.range[0], state); traverse(node.init, path, state); @@ -11855,6 +13511,26 @@ function getDestructuredComponents(node, state) { continue; } + if (item.type === Syntax.SpreadElement) { + // Spread/rest of an array. + // TODO(dmitrys): support spread in the middle of a pattern + // and also for function param patterns: [x, ...xs, y] + components.push(item.argument.name + + '=Array.prototype.slice.call(' + + utils.getTempVar(tmpIndex) + ',' + idx + ')' + ); + continue; + } + + if (item.type === Syntax.SpreadProperty) { + var restExpression = restPropertyHelpers.renderRestExpression( + utils.getTempVar(tmpIndex), + patternItems + ); + components.push(item.argument.name + '=' + restExpression); + continue; + } + // Depending on pattern type (Array or Object), we get // corresponding pattern item parts. var accessor = getPatternItemAccessor(node, item, tmpIndex, idx); @@ -11864,19 +13540,11 @@ function getDestructuredComponents(node, state) { if (value.type === Syntax.Identifier) { // Simple pattern item. components.push(value.name + '=' + accessor); - } else if (value.type === Syntax.SpreadElement) { - // Spread/rest of an array. - // TODO(dmitrys): support spread in the middle of a pattern - // and also for function param patterns: [x, ...xs, y] - components.push(value.argument.name + - '=Array.prototype.slice.call(' + - getTmpVar(tmpIndex) + ',' + idx + ')' - ); } else { // Complex sub-structure. components.push( - getInitialValue(++state.localScope.tempVarIndex, accessor) + ',' + - getDestructuredComponents(value, state) + utils.getTempVarWithValue(++state.localScope.tempVarIndex, accessor) + + ',' + getDestructuredComponents(value, state) ); } } @@ -11889,10 +13557,18 @@ function getPatternItems(node) { } function getPatternItemAccessor(node, patternItem, tmpIndex, idx) { - var tmpName = getTmpVar(tmpIndex); - return node.type === Syntax.ObjectPattern - ? tmpName + '.' + patternItem.key.name - : tmpName + '[' + idx + ']'; + var tmpName = utils.getTempVar(tmpIndex); + if (node.type === Syntax.ObjectPattern) { + if (reservedWordsHelper.isReservedWord(patternItem.key.name)) { + return tmpName + '["' + patternItem.key.name + '"]'; + } else if (patternItem.key.type === Syntax.Literal) { + return tmpName + '[' + JSON.stringify(patternItem.key.value) + ']'; + } else if (patternItem.key.type === Syntax.Identifier) { + return tmpName + '.' + patternItem.key.name; + } + } else if (node.type === Syntax.ArrayPattern) { + return tmpName + '[' + idx + ']'; + } } function getPatternItemValue(node, patternItem) { @@ -11901,14 +13577,6 @@ function getPatternItemValue(node, patternItem) { : patternItem; } -function getInitialValue(index, value) { - return getTmpVar(index) + '=' + value; -} - -function getTmpVar(index) { - return '$__' + index; -} - // ------------------------------------------------------- // 2. Assignment expression. // @@ -11918,14 +13586,14 @@ function getTmpVar(index) { function visitStructuredAssignment(traverse, node, path, state) { var exprNode = node.expression; - utils.append('var ' + getTmpVar(state.localScope.tempVarIndex) + '=', state); + utils.append('var ' + utils.getTempVar(state.localScope.tempVarIndex) + '=', state); utils.catchupWhiteSpace(exprNode.right.range[0], state); traverse(exprNode.right, path, state); utils.catchup(exprNode.right.range[1], state); utils.append( - ',' + getDestructuredComponents(exprNode.left, state) + ';', + ';' + getDestructuredComponents(exprNode.left, state) + ';', state ); @@ -11950,7 +13618,7 @@ visitStructuredAssignment.test = function(node, path, state) { // ------------------------------------------------------- function visitStructuredParameter(traverse, node, path, state) { - utils.append(getTmpVar(getParamIndex(node, path)), state); + utils.append(utils.getTempVar(getParamIndex(node, path)), state); utils.catchupWhiteSpace(node.range[1], state); return true; } @@ -11995,7 +13663,7 @@ function visitFunctionBodyForStructuredParameter(traverse, node, path, state) { if (funcNode.rest) { utils.append( - restParamVisitors.renderRestParamSetup(funcNode), + restParamVisitors.renderRestParamSetup(funcNode, state), state ); } @@ -12035,7 +13703,7 @@ exports.visitorList = [ exports.renderDestructuredComponents = renderDestructuredComponents; -},{"../src/utils":20,"./es6-rest-param-visitors":26,"esprima-fb":6}],24:[function(_dereq_,module,exports){ +},{"../src/utils":22,"./es6-rest-param-visitors":28,"./es7-rest-property-helpers":30,"./reserved-words-helper":32,"esprima-fb":9}],26:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -12055,7 +13723,7 @@ exports.renderDestructuredComponents = renderDestructuredComponents; /*jslint node:true*/ /** - * Desugars concise methods of objects to ES3 function expressions. + * Desugars concise methods of objects to function expressions. * * var foo = { * method(x, y) { ... } @@ -12069,10 +13737,27 @@ exports.renderDestructuredComponents = renderDestructuredComponents; var Syntax = _dereq_('esprima-fb').Syntax; var utils = _dereq_('../src/utils'); +var reservedWordsHelper = _dereq_('./reserved-words-helper'); function visitObjectConciseMethod(traverse, node, path, state) { + var isGenerator = node.value.generator; + if (isGenerator) { + utils.catchupWhiteSpace(node.range[0] + 1, state); + } + if (node.computed) { // [<expr>]() { ...} + utils.catchup(node.key.range[1] + 1, state); + } else if (reservedWordsHelper.isReservedWord(node.key.name)) { + utils.catchup(node.key.range[0], state); + utils.append('"', state); + utils.catchup(node.key.range[1], state); + utils.append('"', state); + } + utils.catchup(node.key.range[1], state); - utils.append(':function', state); + utils.append( + ':function' + (isGenerator ? '*' : ''), + state + ); path.unshift(node); traverse(node.value, path, state); path.shift(); @@ -12089,7 +13774,7 @@ exports.visitorList = [ visitObjectConciseMethod ]; -},{"../src/utils":20,"esprima-fb":6}],25:[function(_dereq_,module,exports){ +},{"../src/utils":22,"./reserved-words-helper":32,"esprima-fb":9}],27:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -12116,7 +13801,7 @@ exports.visitorList = [ * return {x, y}; // {x: x, y: y} * }; * - * // Destrucruting. + * // Destructuring. * function init({port, ip, coords: {x, y}}) { ... } * */ @@ -12144,7 +13829,7 @@ exports.visitorList = [ ]; -},{"../src/utils":20,"esprima-fb":6}],26:[function(_dereq_,module,exports){ +},{"../src/utils":22,"esprima-fb":9}],28:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -12164,16 +13849,20 @@ exports.visitorList = [ /*jslint node:true*/ /** - * Desugars ES6 rest parameters into ES3 arguments slicing. + * Desugars ES6 rest parameters into an ES3 arguments array. * * function printf(template, ...args) { * args.forEach(...); - * }; + * } + * + * We could use `Array.prototype.slice.call`, but that usage of arguments causes + * functions to be deoptimized in V8, so instead we use a for-loop. * * function printf(template) { - * var args = [].slice.call(arguments, 1); + * for (var args = [], $__0 = 1, $__1 = arguments.length; $__0 < $__1; $__0++) + * args.push(arguments[$__0]); * args.forEach(...); - * }; + * } * */ var Syntax = _dereq_('esprima-fb').Syntax; @@ -12218,17 +13907,22 @@ visitFunctionParamsWithRestParam.test = function(node, path, state) { return _nodeIsFunctionWithRestParam(node); }; -function renderRestParamSetup(functionNode) { - return 'var ' + functionNode.rest.name + '=Array.prototype.slice.call(' + - 'arguments,' + - functionNode.params.length + - ');'; +function renderRestParamSetup(functionNode, state) { + var idx = state.localScope.tempVarIndex++; + var len = state.localScope.tempVarIndex++; + + return 'for (var ' + functionNode.rest.name + '=[],' + + utils.getTempVarWithValue(idx, functionNode.params.length) + ',' + + utils.getTempVarWithValue(len, 'arguments.length') + ';' + + utils.getTempVar(idx) + '<' + utils.getTempVar(len) + ';' + + utils.getTempVar(idx) + '++) ' + + functionNode.rest.name + '.push(arguments[' + utils.getTempVar(idx) + ']);'; } function visitFunctionBodyWithRestParam(traverse, node, path, state) { utils.catchup(node.range[0] + 1, state); var parentNode = path[0]; - utils.append(renderRestParamSetup(parentNode), state); + utils.append(renderRestParamSetup(parentNode, state), state); return true; } @@ -12243,7 +13937,7 @@ exports.visitorList = [ visitFunctionBodyWithRestParam ]; -},{"../src/utils":20,"esprima-fb":6}],27:[function(_dereq_,module,exports){ +},{"../src/utils":22,"esprima-fb":9}],29:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -12401,9 +14095,9 @@ exports.visitorList = [ visitTaggedTemplateExpression ]; -},{"../src/utils":20,"esprima-fb":6}],28:[function(_dereq_,module,exports){ +},{"../src/utils":22,"esprima-fb":9}],30:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * 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. @@ -12417,319 +14111,186 @@ exports.visitorList = [ * See the License for the specific language governing permissions and * limitations under the License. */ -/* jshint browser: true */ -/* jslint evil: true */ - -'use strict'; -var buffer = _dereq_('buffer'); -var docblock = _dereq_('jstransform/src/docblock'); -var transform = _dereq_('jstransform').transform; -var visitors = _dereq_('./fbtransform/visitors'); - -var headEl; -var dummyAnchor; -var inlineScriptCount = 0; - -// The source-map library relies on Object.defineProperty, but IE8 doesn't -// support it fully even with es5-sham. Indeed, es5-sham's defineProperty -// throws when Object.prototype.__defineGetter__ is missing, so we skip building -// the source map in that case. -var supportsAccessors = Object.prototype.hasOwnProperty('__defineGetter__'); +/*jslint node:true*/ /** - * Run provided code through jstransform. - * - * @param {string} source Original source code - * @param {object?} options Options to pass to jstransform - * @return {object} object as returned from jstransform + * Desugars ES7 rest properties into ES5 object iteration. */ -function transformReact(source, options) { - // TODO: just use react-tools - var visitorList; - if (options && options.harmony) { - visitorList = visitors.getAllVisitors(); - } else { - visitorList = visitors.transformVisitors.react; + +var Syntax = _dereq_('esprima-fb').Syntax; +var utils = _dereq_('../src/utils'); + +// TODO: This is a pretty massive helper, it should only be defined once, in the +// transform's runtime environment. We don't currently have a runtime though. +var restFunction = + '(function(source, exclusion) {' + + 'var rest = {};' + + 'var hasOwn = Object.prototype.hasOwnProperty;' + + 'if (source == null) {' + + 'throw new TypeError();' + + '}' + + 'for (var key in source) {' + + 'if (hasOwn.call(source, key) && !hasOwn.call(exclusion, key)) {' + + 'rest[key] = source[key];' + + '}' + + '}' + + 'return rest;' + + '})'; + +function getPropertyNames(properties) { + var names = []; + for (var i = 0; i < properties.length; i++) { + var property = properties[i]; + if (property.type === Syntax.SpreadProperty) { + continue; + } + if (property.type === Syntax.Identifier) { + names.push(property.name); + } else { + names.push(property.key.name); + } } + return names; +} - return transform(visitorList, source, { - sourceMap: supportsAccessors - }); +function getRestFunctionCall(source, exclusion) { + return restFunction + '(' + source + ',' + exclusion + ')'; +} + +function getSimpleShallowCopy(accessorExpression) { + // This could be faster with 'Object.assign({}, ' + accessorExpression + ')' + // but to unify code paths and avoid a ES6 dependency we use the same + // helper as for the exclusion case. + return getRestFunctionCall(accessorExpression, '{}'); +} + +function renderRestExpression(accessorExpression, excludedProperties) { + var excludedNames = getPropertyNames(excludedProperties); + if (!excludedNames.length) { + return getSimpleShallowCopy(accessorExpression); + } + return getRestFunctionCall( + accessorExpression, + '{' + excludedNames.join(':1,') + ':1}' + ); } +exports.renderRestExpression = renderRestExpression; + +},{"../src/utils":22,"esprima-fb":9}],31:[function(_dereq_,module,exports){ /** - * Eval provided source after transforming it. - * - * @param {string} source Original source code - * @param {object?} options Options to pass to jstransform + * Copyright 2004-present Facebook. All Rights Reserved. */ -function exec(source, options) { - return eval(transformReact(source, options).code); -} +/*global exports:true*/ /** - * This method returns a nicely formated line of code pointing to the exact - * location of the error `e`. The line is limited in size so big lines of code - * are also shown in a readable way. + * Implements ES7 object spread property. + * https://gist.github.com/sebmarkbage/aa849c7973cb4452c547 * - * Example: - * ... x', overflow:'scroll'}} id={} onScroll={this.scroll} class=" ... - * ^ + * { ...a, x: 1 } + * + * Object.assign({}, a, {x: 1 }) * - * @param {string} code The full string of code - * @param {Error} e The error being thrown - * @return {string} formatted message - * @internal */ -function createSourceCodeErrorMessage(code, e) { - var sourceLines = code.split('\n'); - var erroneousLine = sourceLines[e.lineNumber - 1]; - // Removes any leading indenting spaces and gets the number of - // chars indenting the `erroneousLine` - var indentation = 0; - erroneousLine = erroneousLine.replace(/^\s+/, function(leadingSpaces) { - indentation = leadingSpaces.length; - return ''; - }); +var Syntax = _dereq_('esprima-fb').Syntax; +var utils = _dereq_('../src/utils'); - // Defines the number of characters that are going to show - // before and after the erroneous code - var LIMIT = 30; - var errorColumn = e.column - indentation; +function visitObjectLiteralSpread(traverse, node, path, state) { + utils.catchup(node.range[0], state); - if (errorColumn > LIMIT) { - erroneousLine = '... ' + erroneousLine.slice(errorColumn - LIMIT); - errorColumn = 4 + LIMIT; - } - if (erroneousLine.length - errorColumn > LIMIT) { - erroneousLine = erroneousLine.slice(0, errorColumn + LIMIT) + ' ...'; - } - var message = '\n\n' + erroneousLine + '\n'; - message += new Array(errorColumn - 1).join(' ') + '^'; - return message; -} + utils.append('Object.assign({', state); -/** - * Actually transform the code. - * - * @param {string} code - * @param {string?} url - * @param {object?} options - * @return {string} The transformed code. - * @internal - */ -function transformCode(code, url, options) { - var jsx = docblock.parseAsObject(docblock.extract(code)).jsx; - - if (jsx) { - try { - var transformed = transformReact(code, options); - } catch(e) { - e.message += '\n at '; - if (url) { - if ('fileName' in e) { - // We set `fileName` if it's supported by this error object and - // a `url` was provided. - // The error will correctly point to `url` in Firefox. - e.fileName = url; - } - e.message += url + ':' + e.lineNumber + ':' + e.column; - } else { - e.message += location.href; - } - e.message += createSourceCodeErrorMessage(code, e); - throw e; - } + // Skip the original { + utils.move(node.range[0] + 1, state); - if (!transformed.sourceMap) { - return transformed.code; - } + var previousWasSpread = false; + + for (var i = 0; i < node.properties.length; i++) { + var property = node.properties[i]; + if (property.type === Syntax.SpreadProperty) { - var map = transformed.sourceMap.toJSON(); - var source; - if (url == null) { - source = "Inline JSX script"; - inlineScriptCount++; - if (inlineScriptCount > 1) { - source += ' (' + inlineScriptCount + ')'; + // Close the previous object or initial object + if (!previousWasSpread) { + utils.append('}', state); } - } else if (dummyAnchor) { - // Firefox has problems when the sourcemap source is a proper URL with a - // protocol and hostname, so use the pathname. We could use just the - // filename, but hopefully using the full path will prevent potential - // issues where the same filename exists in multiple directories. - dummyAnchor.href = url; - source = dummyAnchor.pathname.substr(1); - } - map.sources = [source]; - map.sourcesContent = [code]; - - return ( - transformed.code + - '\n//# sourceMappingURL=data:application/json;base64,' + - buffer.Buffer(JSON.stringify(map)).toString('base64') - ); - } else { - // TODO: warn that we found a script tag missing the docblock? - // or warn and proceed anyway? - // or warn, add it ourselves, and proceed anyway? - return code; - } -} + if (i === 0) { + // Normally there will be a comma when we catch up, but not before + // the first property. + utils.append(',', state); + } -/** - * Appends a script element at the end of the <head> with the content of code, - * after transforming it. - * - * @param {string} code The original source code - * @param {string?} url Where the code came from. null if inline - * @param {object?} options Options to pass to jstransform - * @internal - */ -function run(code, url, options) { - var scriptEl = document.createElement('script'); - scriptEl.text = transformCode(code, url, options); - headEl.appendChild(scriptEl); -} + utils.catchup(property.range[0], state); -/** - * Load script from the provided url and pass the content to the callback. - * - * @param {string} url The location of the script src - * @param {function} callback Function to call with the content of url - * @internal - */ -function load(url, callback) { - var xhr; - xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') - : new XMLHttpRequest(); + // skip ... + utils.move(property.range[0] + 3, state); - // async, however scripts will be executed in the order they are in the - // DOM to mirror normal script loading. - xhr.open('GET', url, true); - if ('overrideMimeType' in xhr) { - xhr.overrideMimeType('text/plain'); - } - xhr.onreadystatechange = function() { - if (xhr.readyState === 4) { - if (xhr.status === 0 || xhr.status === 200) { - callback(xhr.responseText, url); - } else { - throw new Error("Could not load " + url); - } - } - }; - return xhr.send(null); -} + traverse(property.argument, path, state); -/** - * Loop over provided script tags and get the content, via innerHTML if an - * inline script, or by using XHR. Transforms are applied if needed. The scripts - * are executed in the order they are found on the page. - * - * @param {array} scripts The <script> elements to load and run. - * @internal - */ -function loadScripts(scripts) { - var result = scripts.map(function() { - return false; - }); - var count = result.length; + utils.catchup(property.range[1], state); - function check() { - var script, i; + previousWasSpread = true; - for (i = 0; i < count; i++) { - script = result[i]; + } else { - if (script && !script.executed) { - run(script.content, script.url, script.options); - script.executed = true; - } else if (!script) { - break; + utils.catchup(property.range[0], state); + + if (previousWasSpread) { + utils.append('{', state); } - } - } - scripts.forEach(function(script, i) { - var options; - if (script.type.indexOf('harmony=true') !== -1) { - options = { - harmony: true - }; - } + traverse(property, path, state); - if (script.src) { - load(script.src, function(content, url) { - result[i] = { - executed: false, - content: content, - url: url, - options: options - }; - check(); - }); - } else { - result[i] = { - executed: false, - content: script.innerHTML, - url: null, - options: options - }; - check(); - } - }); -} + utils.catchup(property.range[1], state); -/** - * Find and run all script tags with type="text/jsx". - * - * @internal - */ -function runScripts() { - var scripts = document.getElementsByTagName('script'); + previousWasSpread = false; - // Array.prototype.slice cannot be used on NodeList on IE8 - var jsxScripts = []; - for (var i = 0; i < scripts.length; i++) { - if (scripts.item(i).type.indexOf('text/jsx') !== -1) { - jsxScripts.push(scripts.item(i)); } } - console.warn( - 'You are using the in-browser JSX transformer. Be sure to precompile ' + - 'your JSX for production - ' + - 'http://facebook.github.io/react/docs/tooling-integration.html#jsx' - ); - - loadScripts(jsxScripts); -} + // Strip any non-whitespace between the last item and the end. + // We only catch up on whitespace so that we ignore any trailing commas which + // are stripped out for IE8 support. Unfortunately, this also strips out any + // trailing comments. + utils.catchupWhiteSpace(node.range[1] - 1, state); -// Listen for load event if we're in a browser and then kick off finding and -// running of scripts. -if (typeof window !== "undefined" && window !== null) { - headEl = document.getElementsByTagName('head')[0]; - dummyAnchor = document.createElement('a'); + // Skip the trailing } + utils.move(node.range[1], state); - if (window.addEventListener) { - window.addEventListener('DOMContentLoaded', runScripts, false); - } else { - window.attachEvent('onload', runScripts); + if (!previousWasSpread) { + utils.append('}', state); } + + utils.append(')', state); + return false; } -module.exports = { - transform: transformReact, - exec: exec +visitObjectLiteralSpread.test = function(node, path, state) { + if (node.type !== Syntax.ObjectExpression) { + return false; + } + // Tight loop optimization + var hasAtLeastOneSpreadProperty = false; + for (var i = 0; i < node.properties.length; i++) { + var property = node.properties[i]; + if (property.type === Syntax.SpreadProperty) { + hasAtLeastOneSpreadProperty = true; + } else if (property.kind !== 'init') { + return false; + } + } + return hasAtLeastOneSpreadProperty; }; -},{"./fbtransform/visitors":32,"buffer":1,"jstransform":19,"jstransform/src/docblock":18}],29:[function(_dereq_,module,exports){ +exports.visitorList = [ + visitObjectLiteralSpread +]; + +},{"../src/utils":22,"esprima-fb":9}],32:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2014 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12743,10 +14304,203 @@ module.exports = { * See the License for the specific language governing permissions and * limitations under the License. */ + +var KEYWORDS = [ + 'break', 'do', 'in', 'typeof', 'case', 'else', 'instanceof', 'var', 'catch', + 'export', 'new', 'void', 'class', 'extends', 'return', 'while', 'const', + 'finally', 'super', 'with', 'continue', 'for', 'switch', 'yield', 'debugger', + 'function', 'this', 'default', 'if', 'throw', 'delete', 'import', 'try' +]; + +var FUTURE_RESERVED_WORDS = [ + 'enum', 'await', 'implements', 'package', 'protected', 'static', 'interface', + 'private', 'public' +]; + +var LITERALS = [ + 'null', + 'true', + 'false' +]; + +// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-reserved-words +var RESERVED_WORDS = [].concat( + KEYWORDS, + FUTURE_RESERVED_WORDS, + LITERALS +); + +var reservedWordsMap = Object.create(null); +RESERVED_WORDS.forEach(function(k) { + reservedWordsMap[k] = true; +}); + +exports.isReservedWord = function(word) { + return !!reservedWordsMap[word]; +}; + +},{}],33:[function(_dereq_,module,exports){ +var esprima = _dereq_('esprima-fb'); +var utils = _dereq_('../src/utils'); + +var Syntax = esprima.Syntax; + +function _isFunctionNode(node) { + return node.type === Syntax.FunctionDeclaration + || node.type === Syntax.FunctionExpression + || node.type === Syntax.ArrowFunctionExpression; +} + +function visitClassProperty(traverse, node, path, state) { + utils.catchup(node.range[0], state); + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitClassProperty.test = function(node, path, state) { + return node.type === Syntax.ClassProperty; +}; + +function visitTypeAlias(traverse, node, path, state) { + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitTypeAlias.test = function(node, path, state) { + return node.type === Syntax.TypeAlias; +}; + +function visitInterfaceDeclaration(traverse, node, path, state) { + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitInterfaceDeclaration.test = function(node, path, state) { + return node.type === Syntax.InterfaceDeclaration; +}; + +function visitDeclare(traverse, node, path, state) { + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitDeclare.test = function(node, path, state) { + switch (node.type) { + case Syntax.DeclareVariable: + case Syntax.DeclareFunction: + case Syntax.DeclareClass: + case Syntax.DeclareModule: return true + } + return false; +} + +function visitFunctionParametricAnnotation(traverse, node, path, state) { + utils.catchup(node.range[0], state); + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitFunctionParametricAnnotation.test = function(node, path, state) { + return node.type === Syntax.TypeParameterDeclaration + && path[0] + && _isFunctionNode(path[0]) + && node === path[0].typeParameters; +}; + +function visitFunctionReturnAnnotation(traverse, node, path, state) { + utils.catchup(node.range[0], state); + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitFunctionReturnAnnotation.test = function(node, path, state) { + return path[0] && _isFunctionNode(path[0]) && node === path[0].returnType; +}; + +function visitOptionalFunctionParameterAnnotation(traverse, node, path, state) { + utils.catchup(node.range[0] + node.name.length, state); + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitOptionalFunctionParameterAnnotation.test = function(node, path, state) { + return node.type === Syntax.Identifier + && node.optional + && path[0] + && _isFunctionNode(path[0]); +}; + +function visitTypeAnnotatedIdentifier(traverse, node, path, state) { + utils.catchup(node.typeAnnotation.range[0], state); + utils.catchupWhiteOut(node.typeAnnotation.range[1], state); + return false; +} +visitTypeAnnotatedIdentifier.test = function(node, path, state) { + return node.type === Syntax.Identifier && node.typeAnnotation; +}; + +function visitTypeAnnotatedObjectOrArrayPattern(traverse, node, path, state) { + utils.catchup(node.typeAnnotation.range[0], state); + utils.catchupWhiteOut(node.typeAnnotation.range[1], state); + return false; +} +visitTypeAnnotatedObjectOrArrayPattern.test = function(node, path, state) { + var rightType = node.type === Syntax.ObjectPattern + || node.type === Syntax.ArrayPattern; + return rightType && node.typeAnnotation; +}; + +/** + * Methods cause trouble, since esprima parses them as a key/value pair, where + * the location of the value starts at the method body. For example + * { bar(x:number,...y:Array<number>):number {} } + * is parsed as + * { bar: function(x: number, ...y:Array<number>): number {} } + * except that the location of the FunctionExpression value is 40-something, + * which is the location of the function body. This means that by the time we + * visit the params, rest param, and return type organically, we've already + * catchup()'d passed them. + */ +function visitMethod(traverse, node, path, state) { + path.unshift(node); + traverse(node.key, path, state); + + path.unshift(node.value); + traverse(node.value.params, path, state); + node.value.rest && traverse(node.value.rest, path, state); + node.value.returnType && traverse(node.value.returnType, path, state); + traverse(node.value.body, path, state); + + path.shift(); + + path.shift(); + return false; +} + +visitMethod.test = function(node, path, state) { + return (node.type === "Property" && (node.method || node.kind === "set" || node.kind === "get")) + || (node.type === "MethodDefinition"); +}; + +exports.visitorList = [ + visitClassProperty, + visitDeclare, + visitInterfaceDeclaration, + visitFunctionParametricAnnotation, + visitFunctionReturnAnnotation, + visitMethod, + visitOptionalFunctionParameterAnnotation, + visitTypeAlias, + visitTypeAnnotatedIdentifier, + visitTypeAnnotatedObjectOrArrayPattern +]; + +},{"../src/utils":22,"esprima-fb":9}],34:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ /*global exports:true*/ "use strict"; -var Syntax = _dereq_('esprima-fb').Syntax; +var Syntax = _dereq_('jstransform').Syntax; var utils = _dereq_('jstransform/src/utils'); var FALLBACK_TAGS = _dereq_('./xjs').knownTags; @@ -12758,27 +14512,16 @@ var quoteAttrName = _dereq_('./xjs').quoteAttrName; var trimLeft = _dereq_('./xjs').trimLeft; /** - * Customized desugar processor. - * - * Currently: (Somewhat tailored to React) - * <X> </X> => X(null, null) - * <X prop="1" /> => X({prop: '1'}, null) - * <X prop="2"><Y /></X> => X({prop:'2'}, Y(null, null)) - * <X prop="2"><Y /><Z /></X> => X({prop:'2'}, [Y(null, null), Z(null, null)]) + * Customized desugar processor for React JSX. Currently: * - * Exceptions to the simple rules above: - * if a property is named "class" it will be changed to "className" in the - * javascript since "class" is not a valid object key in javascript. + * <X> </X> => React.createElement(X, null) + * <X prop="1" /> => React.createElement(X, {prop: '1'}, null) + * <X prop="2"><Y /></X> => React.createElement(X, {prop:'2'}, + * React.createElement(Y, null) + * ) + * <div /> => React.createElement("div", null) */ -var JSX_ATTRIBUTE_TRANSFORMS = { - cxName: function(attr) { - throw new Error( - "cxName is no longer supported, use className={cx(...)} instead" - ); - } -}; - /** * Removes all non-whitespace/parenthesis characters */ @@ -12787,8 +14530,12 @@ function stripNonWhiteParen(value) { return value.replace(reNonWhiteParen, ''); } +var tagConvention = /^[a-z]|\-/; +function isTagName(name) { + return tagConvention.test(name); +} + function visitReactTag(traverse, object, path, state) { - var jsxObjIdent = utils.getDocblock(state).jsx; var openingElement = object.openingElement; var nameObject = openingElement.name; var attributesObject = openingElement.attributes; @@ -12799,44 +14546,31 @@ function visitReactTag(traverse, object, path, state) { throw new Error('Namespace tags are not supported. ReactJSX is not XML.'); } - // Only identifiers can be fallback tags or need quoting. We don't need to - // handle quoting for other types. - var didAddTag = false; - - // Only identifiers can be fallback tags. XJSMemberExpressions are not. - if (nameObject.type === Syntax.XJSIdentifier) { - var tagName = nameObject.name; - var quotedTagName = quoteAttrName(tagName); - - if (FALLBACK_TAGS.hasOwnProperty(tagName)) { - // "Properly" handle invalid identifiers, like <font-face>, which needs to - // be enclosed in quotes. - var predicate = - tagName === quotedTagName ? - ('.' + tagName) : - ('[' + quotedTagName + ']'); - utils.append(jsxObjIdent + predicate, state); - utils.move(nameObject.range[1], state); - didAddTag = true; - } else if (tagName !== quotedTagName) { - // If we're in the case where we need to quote and but don't recognize the - // tag, throw. + // We assume that the React runtime is already in scope + utils.append('React.createElement(', state); + + // Identifiers with lower case or hypthens are fallback tags (strings). + // XJSMemberExpressions are not. + if (nameObject.type === Syntax.XJSIdentifier && isTagName(nameObject.name)) { + // This is a temporary error message to assist upgrades + if (!FALLBACK_TAGS.hasOwnProperty(nameObject.name)) { throw new Error( - 'Tags must be valid JS identifiers or a recognized special case. `<' + - tagName + '>` is not one of them.' + 'Lower case component names (' + nameObject.name + ') are no longer ' + + 'supported in JSX: See http://fb.me/react-jsx-lower-case' ); } - } - // Use utils.catchup in this case so we can easily handle XJSMemberExpressions - // which look like Foo.Bar.Baz. This also handles unhyphenated XJSIdentifiers - // that aren't fallback tags. - if (!didAddTag) { + utils.append('"' + nameObject.name + '"', state); + utils.move(nameObject.range[1], state); + } else { + // Use utils.catchup in this case so we can easily handle + // XJSMemberExpressions which look like Foo.Bar.Baz. This also handles + // XJSIdentifiers that aren't fallback tags. utils.move(nameObject.range[0], state); utils.catchup(nameObject.range[1], state); } - utils.append('(', state); + utils.append(', ', state); var hasAttributes = attributesObject.length; @@ -12846,7 +14580,7 @@ function visitReactTag(traverse, object, path, state) { // if we don't have any attributes, pass in null if (hasAtLeastOneSpreadProperty) { - utils.append('Object.assign({', state); + utils.append('React.__spread({', state); } else if (hasAttributes) { utils.append('{', state); } else { @@ -12861,9 +14595,6 @@ function visitReactTag(traverse, object, path, state) { var isLast = index === attributesObject.length - 1; if (attr.type === Syntax.XJSSpreadAttribute) { - // Plus 1 to skip `{`. - utils.move(attr.range[0] + 1, state); - // Close the previous object or initial object if (!previousWasSpread) { utils.append('}, ', state); @@ -12871,6 +14602,9 @@ function visitReactTag(traverse, object, path, state) { // Move to the expression start, ignoring everything except parenthesis // and whitespace. + utils.catchup(attr.range[0], state, stripNonWhiteParen); + // Plus 1 to skip `{`. + utils.move(attr.range[0] + 1, state); utils.catchup(attr.argument.range[0], state, stripNonWhiteParen); traverse(attr.argument, path, state); @@ -12921,13 +14655,7 @@ function visitReactTag(traverse, object, path, state) { utils.move(attr.name.range[1], state); // Use catchupNewlines to skip over the '=' in the attribute utils.catchupNewlines(attr.value.range[0], state); - if (JSX_ATTRIBUTE_TRANSFORMS.hasOwnProperty(attr.name.name)) { - utils.append(JSX_ATTRIBUTE_TRANSFORMS[attr.name.name](attr), state); - utils.move(attr.value.range[1], state); - if (!isLast) { - utils.append(', ', state); - } - } else if (attr.value.type === Syntax.Literal) { + if (attr.value.type === Syntax.Literal) { renderXJSLiteral(attr.value, isLast, state); } else { renderXJSExpressionContainer(traverse, attr.value, isLast, path, state); @@ -13008,35 +14736,26 @@ function visitReactTag(traverse, object, path, state) { } visitReactTag.test = function(object, path, state) { - // only run react when react @jsx namespace is specified in docblock - var jsx = utils.getDocblock(state).jsx; - return object.type === Syntax.XJSElement && jsx && jsx.length; + return object.type === Syntax.XJSElement; }; exports.visitorList = [ visitReactTag ]; -},{"./xjs":31,"esprima-fb":6,"jstransform/src/utils":20}],30:[function(_dereq_,module,exports){ +},{"./xjs":36,"jstransform":21,"jstransform/src/utils":22}],35:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. */ /*global exports:true*/ "use strict"; -var Syntax = _dereq_('esprima-fb').Syntax; +var Syntax = _dereq_('jstransform').Syntax; var utils = _dereq_('jstransform/src/utils'); function addDisplayName(displayName, object, state) { @@ -13107,44 +14826,30 @@ function visitReactDisplayName(traverse, object, path, state) { } } -/** - * Will only run on @jsx files for now. - */ visitReactDisplayName.test = function(object, path, state) { - if (utils.getDocblock(state).jsx) { - return ( - object.type === Syntax.AssignmentExpression || - object.type === Syntax.Property || - object.type === Syntax.VariableDeclarator - ); - } else { - return false; - } + return ( + object.type === Syntax.AssignmentExpression || + object.type === Syntax.Property || + object.type === Syntax.VariableDeclarator + ); }; exports.visitorList = [ visitReactDisplayName ]; -},{"esprima-fb":6,"jstransform/src/utils":20}],31:[function(_dereq_,module,exports){ +},{"jstransform":21,"jstransform/src/utils":22}],36:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. */ /*global exports:true*/ "use strict"; -var Syntax = _dereq_('esprima-fb').Syntax; +var Syntax = _dereq_('jstransform').Syntax; var utils = _dereq_('jstransform/src/utils'); var knownTags = { @@ -13237,6 +14942,7 @@ var knownTags = { param: true, path: true, pattern: false, + picture: true, polygon: true, polyline: true, pre: true, @@ -13381,7 +15087,7 @@ exports.renderXJSLiteral = renderXJSLiteral; exports.quoteAttrName = quoteAttrName; exports.trimLeft = trimLeft; -},{"esprima-fb":6,"jstransform/src/utils":20}],32:[function(_dereq_,module,exports){ +},{"jstransform":21,"jstransform/src/utils":22}],37:[function(_dereq_,module,exports){ /*global exports:true*/ var es6ArrowFunctions = _dereq_('jstransform/visitors/es6-arrow-function-visitors'); var es6Classes = _dereq_('jstransform/visitors/es6-class-visitors'); @@ -13390,6 +15096,7 @@ var es6ObjectConciseMethod = _dereq_('jstransform/visitors/es6-object-concise-me var es6ObjectShortNotation = _dereq_('jstransform/visitors/es6-object-short-notation-visitors'); var es6RestParameters = _dereq_('jstransform/visitors/es6-rest-param-visitors'); var es6Templates = _dereq_('jstransform/visitors/es6-template-visitors'); +var es7SpreadProperty = _dereq_('jstransform/visitors/es7-spread-property-visitors'); var react = _dereq_('./transforms/react'); var reactDisplayName = _dereq_('./transforms/reactDisplayName'); @@ -13404,9 +15111,26 @@ var transformVisitors = { 'es6-object-short-notation': es6ObjectShortNotation.visitorList, 'es6-rest-params': es6RestParameters.visitorList, 'es6-templates': es6Templates.visitorList, + 'es7-spread-property': es7SpreadProperty.visitorList, 'react': react.visitorList.concat(reactDisplayName.visitorList) }; +var transformSets = { + 'harmony': [ + 'es6-arrow-functions', + 'es6-object-concise-method', + 'es6-object-short-notation', + 'es6-classes', + 'es6-rest-params', + 'es6-templates', + 'es6-destructuring', + 'es7-spread-property' + ], + 'react': [ + 'react' + ] +}; + /** * Specifies the order in which each transform should run. */ @@ -13418,6 +15142,7 @@ var transformRunOrder = [ 'es6-rest-params', 'es6-templates', 'es6-destructuring', + 'es7-spread-property', 'react' ]; @@ -13438,9 +15163,37 @@ function getAllVisitors(excludes) { return ret; } +/** + * Given a list of visitor set names, return the ordered list of visitors to be + * passed to jstransform. + * + * @param {array} + * @return {array} + */ +function getVisitorsBySet(sets) { + var visitorsToInclude = sets.reduce(function(visitors, set) { + if (!transformSets.hasOwnProperty(set)) { + throw new Error('Unknown visitor set: ' + set); + } + transformSets[set].forEach(function(visitor) { + visitors[visitor] = true; + }); + return visitors; + }, {}); + + var visitorList = []; + for (var i = 0; i < transformRunOrder.length; i++) { + if (visitorsToInclude.hasOwnProperty(transformRunOrder[i])) { + visitorList = visitorList.concat(transformVisitors[transformRunOrder[i]]); + } + } + + return visitorList; +} + +exports.getVisitorsBySet = getVisitorsBySet; exports.getAllVisitors = getAllVisitors; exports.transformVisitors = transformVisitors; -},{"./transforms/react":29,"./transforms/reactDisplayName":30,"jstransform/visitors/es6-arrow-function-visitors":21,"jstransform/visitors/es6-class-visitors":22,"jstransform/visitors/es6-destructuring-visitors":23,"jstransform/visitors/es6-object-concise-method-visitors":24,"jstransform/visitors/es6-object-short-notation-visitors":25,"jstransform/visitors/es6-rest-param-visitors":26,"jstransform/visitors/es6-template-visitors":27}]},{},[28]) -(28) +},{"./transforms/react":34,"./transforms/reactDisplayName":35,"jstransform/visitors/es6-arrow-function-visitors":23,"jstransform/visitors/es6-class-visitors":24,"jstransform/visitors/es6-destructuring-visitors":25,"jstransform/visitors/es6-object-concise-method-visitors":26,"jstransform/visitors/es6-object-short-notation-visitors":27,"jstransform/visitors/es6-rest-param-visitors":28,"jstransform/visitors/es6-template-visitors":29,"jstransform/visitors/es7-spread-property-visitors":31}]},{},[1])(1) });
\ No newline at end of file diff --git a/web/src/vendor/react/react-with-addons.js b/web/src/vendor/react/react-with-addons.js index b45d8205..b637678d 100644 --- a/web/src/vendor/react/react-with-addons.js +++ b/web/src/vendor/react/react-with-addons.js @@ -1,21 +1,66 @@ /** - * React (with addons) v0.11.1 + * React (with addons) v0.12.1 */ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.React=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.React=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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 + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * - * http://www.apache.org/licenses/LICENSE-2.0 + * @providesModule ReactWithAddons + */ + +/** + * This module exists purely in the open source project, and is meant as a way + * to create a separate standalone build of React. This build has "addons", or + * functionality we've built and think might be useful but doesn't have a good + * place to live inside React core. + */ + +"use strict"; + +var LinkedStateMixin = _dereq_("./LinkedStateMixin"); +var React = _dereq_("./React"); +var ReactComponentWithPureRenderMixin = + _dereq_("./ReactComponentWithPureRenderMixin"); +var ReactCSSTransitionGroup = _dereq_("./ReactCSSTransitionGroup"); +var ReactTransitionGroup = _dereq_("./ReactTransitionGroup"); +var ReactUpdates = _dereq_("./ReactUpdates"); + +var cx = _dereq_("./cx"); +var cloneWithProps = _dereq_("./cloneWithProps"); +var update = _dereq_("./update"); + +React.addons = { + CSSTransitionGroup: ReactCSSTransitionGroup, + LinkedStateMixin: LinkedStateMixin, + PureRenderMixin: ReactComponentWithPureRenderMixin, + TransitionGroup: ReactTransitionGroup, + + batchedUpdates: ReactUpdates.batchedUpdates, + classSet: cx, + cloneWithProps: cloneWithProps, + update: update +}; + +if ("production" !== "development") { + React.addons.Perf = _dereq_("./ReactDefaultPerf"); + React.addons.TestUtils = _dereq_("./ReactTestUtils"); +} + +module.exports = React; + +},{"./LinkedStateMixin":25,"./React":31,"./ReactCSSTransitionGroup":34,"./ReactComponentWithPureRenderMixin":39,"./ReactDefaultPerf":56,"./ReactTestUtils":86,"./ReactTransitionGroup":90,"./ReactUpdates":91,"./cloneWithProps":113,"./cx":118,"./update":159}],2:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule AutoFocusMixin * @typechecks static-only @@ -35,21 +80,14 @@ var AutoFocusMixin = { module.exports = AutoFocusMixin; -},{"./focusNode":120}],2:[function(_dereq_,module,exports){ +},{"./focusNode":125}],3:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule BeforeInputEventPlugin * @typechecks static-only @@ -107,6 +145,9 @@ var eventTypes = { // Track characters inserted via keypress and composition events. var fallbackChars = null; +// Track whether we've ever handled a keypress on the space key. +var hasSpaceKeypress = false; + /** * Return whether a native keypress event is assumed to be a command. * This is required because Firefox fires `keypress` events for key commands @@ -176,7 +217,8 @@ var BeforeInputEventPlugin = { return; } - chars = String.fromCharCode(which); + hasSpaceKeypress = true; + chars = SPACEBAR_CHAR; break; case topLevelTypes.topTextInput: @@ -184,8 +226,9 @@ var BeforeInputEventPlugin = { chars = nativeEvent.data; // If it's a spacebar character, assume that we have already handled - // it at the keypress level and bail immediately. - if (chars === SPACEBAR_CHAR) { + // it at the keypress level and bail immediately. Android Chrome + // doesn't give us keycodes, so we need to blacklist it. + if (chars === SPACEBAR_CHAR && hasSpaceKeypress) { return; } @@ -259,21 +302,14 @@ var BeforeInputEventPlugin = { module.exports = BeforeInputEventPlugin; -},{"./EventConstants":16,"./EventPropagators":21,"./ExecutionEnvironment":22,"./SyntheticInputEvent":98,"./keyOf":141}],3:[function(_dereq_,module,exports){ +},{"./EventConstants":17,"./EventPropagators":22,"./ExecutionEnvironment":23,"./SyntheticInputEvent":101,"./keyOf":147}],4:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule CSSCore * @typechecks @@ -359,7 +395,7 @@ var CSSCore = { * * @param {DOMNode|DOMWindow} element the element to set the class on * @param {string} className the CSS className - * @returns {boolean} true if the element has the class, false if not + * @return {boolean} true if the element has the class, false if not */ hasClass: function(element, className) { ("production" !== "development" ? invariant( @@ -376,21 +412,14 @@ var CSSCore = { module.exports = CSSCore; -},{"./invariant":134}],4:[function(_dereq_,module,exports){ +},{"./invariant":140}],5:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule CSSProperty */ @@ -499,21 +528,14 @@ var CSSProperty = { module.exports = CSSProperty; -},{}],5:[function(_dereq_,module,exports){ +},{}],6:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule CSSPropertyOperations * @typechecks static-only @@ -522,15 +544,43 @@ module.exports = CSSProperty; "use strict"; var CSSProperty = _dereq_("./CSSProperty"); +var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); +var camelizeStyleName = _dereq_("./camelizeStyleName"); var dangerousStyleValue = _dereq_("./dangerousStyleValue"); var hyphenateStyleName = _dereq_("./hyphenateStyleName"); var memoizeStringOnly = _dereq_("./memoizeStringOnly"); +var warning = _dereq_("./warning"); var processStyleName = memoizeStringOnly(function(styleName) { return hyphenateStyleName(styleName); }); +var styleFloatAccessor = 'cssFloat'; +if (ExecutionEnvironment.canUseDOM) { + // IE8 only supports accessing cssFloat (standard) as styleFloat + if (document.documentElement.style.cssFloat === undefined) { + styleFloatAccessor = 'styleFloat'; + } +} + +if ("production" !== "development") { + var warnedStyleNames = {}; + + var warnHyphenatedStyleName = function(name) { + if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { + return; + } + + warnedStyleNames[name] = true; + ("production" !== "development" ? warning( + false, + 'Unsupported style property ' + name + '. Did you mean ' + + camelizeStyleName(name) + '?' + ) : null); + }; +} + /** * Operations for dealing with CSS properties. */ @@ -554,6 +604,11 @@ var CSSPropertyOperations = { if (!styles.hasOwnProperty(styleName)) { continue; } + if ("production" !== "development") { + if (styleName.indexOf('-') > -1) { + warnHyphenatedStyleName(styleName); + } + } var styleValue = styles[styleName]; if (styleValue != null) { serialized += processStyleName(styleName) + ':'; @@ -576,7 +631,15 @@ var CSSPropertyOperations = { if (!styles.hasOwnProperty(styleName)) { continue; } + if ("production" !== "development") { + if (styleName.indexOf('-') > -1) { + warnHyphenatedStyleName(styleName); + } + } var styleValue = dangerousStyleValue(styleName, styles[styleName]); + if (styleName === 'float') { + styleName = styleFloatAccessor; + } if (styleValue) { style[styleName] = styleValue; } else { @@ -598,21 +661,14 @@ var CSSPropertyOperations = { module.exports = CSSPropertyOperations; -},{"./CSSProperty":4,"./dangerousStyleValue":115,"./hyphenateStyleName":132,"./memoizeStringOnly":143}],6:[function(_dereq_,module,exports){ +},{"./CSSProperty":5,"./ExecutionEnvironment":23,"./camelizeStyleName":112,"./dangerousStyleValue":119,"./hyphenateStyleName":138,"./memoizeStringOnly":149,"./warning":160}],7:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule CallbackQueue */ @@ -621,8 +677,8 @@ module.exports = CSSPropertyOperations; var PooledClass = _dereq_("./PooledClass"); +var assign = _dereq_("./Object.assign"); var invariant = _dereq_("./invariant"); -var mixInto = _dereq_("./mixInto"); /** * A specialized pseudo-event module to help keep track of components waiting to @@ -640,7 +696,7 @@ function CallbackQueue() { this._contexts = null; } -mixInto(CallbackQueue, { +assign(CallbackQueue.prototype, { /** * Enqueues a callback to be invoked when `notifyAll` is invoked. @@ -703,21 +759,14 @@ PooledClass.addPoolingTo(CallbackQueue); module.exports = CallbackQueue; -},{"./PooledClass":28,"./invariant":134,"./mixInto":147}],7:[function(_dereq_,module,exports){ +},{"./Object.assign":29,"./PooledClass":30,"./invariant":140}],8:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ChangeEventPlugin */ @@ -1092,21 +1141,14 @@ var ChangeEventPlugin = { module.exports = ChangeEventPlugin; -},{"./EventConstants":16,"./EventPluginHub":18,"./EventPropagators":21,"./ExecutionEnvironment":22,"./ReactUpdates":87,"./SyntheticEvent":96,"./isEventSupported":135,"./isTextInputElement":137,"./keyOf":141}],8:[function(_dereq_,module,exports){ +},{"./EventConstants":17,"./EventPluginHub":19,"./EventPropagators":22,"./ExecutionEnvironment":23,"./ReactUpdates":91,"./SyntheticEvent":99,"./isEventSupported":141,"./isTextInputElement":143,"./keyOf":147}],9:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ClientReactRootIndex * @typechecks @@ -1124,21 +1166,14 @@ var ClientReactRootIndex = { module.exports = ClientReactRootIndex; -},{}],9:[function(_dereq_,module,exports){ +},{}],10:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule CompositionEventPlugin * @typechecks static-only @@ -1390,21 +1425,14 @@ var CompositionEventPlugin = { module.exports = CompositionEventPlugin; -},{"./EventConstants":16,"./EventPropagators":21,"./ExecutionEnvironment":22,"./ReactInputSelection":63,"./SyntheticCompositionEvent":94,"./getTextContentAccessor":129,"./keyOf":141}],10:[function(_dereq_,module,exports){ +},{"./EventConstants":17,"./EventPropagators":22,"./ExecutionEnvironment":23,"./ReactInputSelection":65,"./SyntheticCompositionEvent":97,"./getTextContentAccessor":135,"./keyOf":147}],11:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule DOMChildrenOperations * @typechecks static-only @@ -1512,9 +1540,9 @@ var DOMChildrenOperations = { 'processUpdates(): Unable to find child %s of element. This ' + 'probably means the DOM was unexpectedly mutated (e.g., by the ' + 'browser), usually due to forgetting a <tbody> when using tables, ' + - 'nesting <p> or <a> tags, or using non-SVG elements in an <svg> '+ - 'parent. Try inspecting the child nodes of the element with React ' + - 'ID `%s`.', + 'nesting tags like <form>, <p>, or <a>, or using non-SVG elements '+ + 'in an <svg> parent. Try inspecting the child nodes of the element ' + + 'with React ID `%s`.', updatedIndex, parentID ) : invariant(updatedChild)); @@ -1570,21 +1598,14 @@ var DOMChildrenOperations = { module.exports = DOMChildrenOperations; -},{"./Danger":13,"./ReactMultiChildUpdateTypes":69,"./getTextContentAccessor":129,"./invariant":134}],11:[function(_dereq_,module,exports){ +},{"./Danger":14,"./ReactMultiChildUpdateTypes":72,"./getTextContentAccessor":135,"./invariant":140}],12:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule DOMProperty * @typechecks static-only @@ -1596,6 +1617,10 @@ module.exports = DOMChildrenOperations; var invariant = _dereq_("./invariant"); +function checkMask(value, bitmask) { + return (value & bitmask) === bitmask; +} + var DOMPropertyInjection = { /** * Mapping from normalized, camelcased property names to a configuration that @@ -1682,19 +1707,19 @@ var DOMPropertyInjection = { var propConfig = Properties[propName]; DOMProperty.mustUseAttribute[propName] = - propConfig & DOMPropertyInjection.MUST_USE_ATTRIBUTE; + checkMask(propConfig, DOMPropertyInjection.MUST_USE_ATTRIBUTE); DOMProperty.mustUseProperty[propName] = - propConfig & DOMPropertyInjection.MUST_USE_PROPERTY; + checkMask(propConfig, DOMPropertyInjection.MUST_USE_PROPERTY); DOMProperty.hasSideEffects[propName] = - propConfig & DOMPropertyInjection.HAS_SIDE_EFFECTS; + checkMask(propConfig, DOMPropertyInjection.HAS_SIDE_EFFECTS); DOMProperty.hasBooleanValue[propName] = - propConfig & DOMPropertyInjection.HAS_BOOLEAN_VALUE; + checkMask(propConfig, DOMPropertyInjection.HAS_BOOLEAN_VALUE); DOMProperty.hasNumericValue[propName] = - propConfig & DOMPropertyInjection.HAS_NUMERIC_VALUE; + checkMask(propConfig, DOMPropertyInjection.HAS_NUMERIC_VALUE); DOMProperty.hasPositiveNumericValue[propName] = - propConfig & DOMPropertyInjection.HAS_POSITIVE_NUMERIC_VALUE; + checkMask(propConfig, DOMPropertyInjection.HAS_POSITIVE_NUMERIC_VALUE); DOMProperty.hasOverloadedBooleanValue[propName] = - propConfig & DOMPropertyInjection.HAS_OVERLOADED_BOOLEAN_VALUE; + checkMask(propConfig, DOMPropertyInjection.HAS_OVERLOADED_BOOLEAN_VALUE); ("production" !== "development" ? invariant( !DOMProperty.mustUseAttribute[propName] || @@ -1870,21 +1895,14 @@ var DOMProperty = { module.exports = DOMProperty; -},{"./invariant":134}],12:[function(_dereq_,module,exports){ +},{"./invariant":140}],13:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule DOMPropertyOperations * @typechecks static-only @@ -2011,10 +2029,17 @@ var DOMPropertyOperations = { } else if (shouldIgnoreValue(name, value)) { this.deleteValueForProperty(node, name); } else if (DOMProperty.mustUseAttribute[name]) { + // `setAttribute` with objects becomes only `[object]` in IE8/9, + // ('' + value) makes it output the correct toString()-value. node.setAttribute(DOMProperty.getAttributeName[name], '' + value); } else { var propName = DOMProperty.getPropertyName[name]; - if (!DOMProperty.hasSideEffects[name] || node[propName] !== value) { + // Must explicitly cast values for HAS_SIDE_EFFECTS-properties to the + // property type before comparing; only `value` does and is string. + if (!DOMProperty.hasSideEffects[name] || + ('' + node[propName]) !== ('' + value)) { + // Contrary to `setAttribute`, object properties are properly + // `toString`ed by IE8/9. node[propName] = value; } } @@ -2050,7 +2075,7 @@ var DOMPropertyOperations = { propName ); if (!DOMProperty.hasSideEffects[name] || - node[propName] !== defaultValue) { + ('' + node[propName]) !== defaultValue) { node[propName] = defaultValue; } } @@ -2065,21 +2090,14 @@ var DOMPropertyOperations = { module.exports = DOMPropertyOperations; -},{"./DOMProperty":11,"./escapeTextForBrowser":118,"./memoizeStringOnly":143,"./warning":158}],13:[function(_dereq_,module,exports){ +},{"./DOMProperty":12,"./escapeTextForBrowser":123,"./memoizeStringOnly":149,"./warning":160}],14:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule Danger * @typechecks static-only @@ -2128,9 +2146,10 @@ var Danger = { dangerouslyRenderMarkup: function(markupList) { ("production" !== "development" ? invariant( ExecutionEnvironment.canUseDOM, - 'dangerouslyRenderMarkup(...): Cannot render markup in a Worker ' + - 'thread. This is likely a bug in the framework. Please report ' + - 'immediately.' + 'dangerouslyRenderMarkup(...): Cannot render markup in a worker ' + + 'thread. Make sure `window` and `document` are available globally ' + + 'before requiring React when unit testing or use ' + + 'React.renderToString for server rendering.' ) : invariant(ExecutionEnvironment.canUseDOM)); var nodeName; var markupByNodeName = {}; @@ -2234,8 +2253,9 @@ var Danger = { ("production" !== "development" ? invariant( ExecutionEnvironment.canUseDOM, 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a ' + - 'worker thread. This is likely a bug in the framework. Please report ' + - 'immediately.' + 'worker thread. Make sure `window` and `document` are available ' + + 'globally before requiring React when unit testing or use ' + + 'React.renderToString for server rendering.' ) : invariant(ExecutionEnvironment.canUseDOM)); ("production" !== "development" ? invariant(markup, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.') : invariant(markup)); ("production" !== "development" ? invariant( @@ -2254,21 +2274,14 @@ var Danger = { module.exports = Danger; -},{"./ExecutionEnvironment":22,"./createNodesFromMarkup":113,"./emptyFunction":116,"./getMarkupWrap":126,"./invariant":134}],14:[function(_dereq_,module,exports){ +},{"./ExecutionEnvironment":23,"./createNodesFromMarkup":117,"./emptyFunction":121,"./getMarkupWrap":132,"./invariant":140}],15:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule DefaultEventPluginOrder */ @@ -2301,21 +2314,14 @@ var DefaultEventPluginOrder = [ module.exports = DefaultEventPluginOrder; -},{"./keyOf":141}],15:[function(_dereq_,module,exports){ +},{"./keyOf":147}],16:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule EnterLeaveEventPlugin * @typechecks static-only @@ -2448,21 +2454,14 @@ var EnterLeaveEventPlugin = { module.exports = EnterLeaveEventPlugin; -},{"./EventConstants":16,"./EventPropagators":21,"./ReactMount":67,"./SyntheticMouseEvent":100,"./keyOf":141}],16:[function(_dereq_,module,exports){ +},{"./EventConstants":17,"./EventPropagators":22,"./ReactMount":70,"./SyntheticMouseEvent":103,"./keyOf":147}],17:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule EventConstants */ @@ -2527,8 +2526,22 @@ var EventConstants = { module.exports = EventConstants; -},{"./keyMirror":140}],17:[function(_dereq_,module,exports){ +},{"./keyMirror":146}],18:[function(_dereq_,module,exports){ /** + * Copyright 2013-2014 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. + * * @providesModule EventListener * @typechecks */ @@ -2601,21 +2614,14 @@ var EventListener = { module.exports = EventListener; -},{"./emptyFunction":116}],18:[function(_dereq_,module,exports){ +},{"./emptyFunction":121}],19:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule EventPluginHub */ @@ -2625,11 +2631,9 @@ module.exports = EventListener; var EventPluginRegistry = _dereq_("./EventPluginRegistry"); var EventPluginUtils = _dereq_("./EventPluginUtils"); -var accumulate = _dereq_("./accumulate"); +var accumulateInto = _dereq_("./accumulateInto"); var forEachAccumulated = _dereq_("./forEachAccumulated"); var invariant = _dereq_("./invariant"); -var isEventSupported = _dereq_("./isEventSupported"); -var monitorCodeUse = _dereq_("./monitorCodeUse"); /** * Internal store for event listeners @@ -2763,15 +2767,6 @@ var EventPluginHub = { registrationName, typeof listener ) : invariant(!listener || typeof listener === 'function')); - if ("production" !== "development") { - // IE8 has no API for event capturing and the `onScroll` event doesn't - // bubble. - if (registrationName === 'onScroll' && - !isEventSupported('scroll', true)) { - monitorCodeUse('react_no_scroll_event'); - console.warn('This browser doesn\'t support the `onScroll` event'); - } - } var bankForRegistrationName = listenerBank[registrationName] || (listenerBank[registrationName] = {}); bankForRegistrationName[id] = listener; @@ -2840,7 +2835,7 @@ var EventPluginHub = { nativeEvent ); if (extractedEvents) { - events = accumulate(events, extractedEvents); + events = accumulateInto(events, extractedEvents); } } } @@ -2856,7 +2851,7 @@ var EventPluginHub = { */ enqueueEvents: function(events) { if (events) { - eventQueue = accumulate(eventQueue, events); + eventQueue = accumulateInto(eventQueue, events); } }, @@ -2893,21 +2888,14 @@ var EventPluginHub = { module.exports = EventPluginHub; -},{"./EventPluginRegistry":19,"./EventPluginUtils":20,"./accumulate":106,"./forEachAccumulated":121,"./invariant":134,"./isEventSupported":135,"./monitorCodeUse":148}],19:[function(_dereq_,module,exports){ +},{"./EventPluginRegistry":20,"./EventPluginUtils":21,"./accumulateInto":109,"./forEachAccumulated":126,"./invariant":140}],20:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule EventPluginRegistry * @typechecks static-only @@ -3178,21 +3166,14 @@ var EventPluginRegistry = { module.exports = EventPluginRegistry; -},{"./invariant":134}],20:[function(_dereq_,module,exports){ +},{"./invariant":140}],21:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule EventPluginUtils */ @@ -3404,21 +3385,14 @@ var EventPluginUtils = { module.exports = EventPluginUtils; -},{"./EventConstants":16,"./invariant":134}],21:[function(_dereq_,module,exports){ +},{"./EventConstants":17,"./invariant":140}],22:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule EventPropagators */ @@ -3428,7 +3402,7 @@ module.exports = EventPluginUtils; var EventConstants = _dereq_("./EventConstants"); var EventPluginHub = _dereq_("./EventPluginHub"); -var accumulate = _dereq_("./accumulate"); +var accumulateInto = _dereq_("./accumulateInto"); var forEachAccumulated = _dereq_("./forEachAccumulated"); var PropagationPhases = EventConstants.PropagationPhases; @@ -3459,8 +3433,9 @@ function accumulateDirectionalDispatches(domID, upwards, event) { var phase = upwards ? PropagationPhases.bubbled : PropagationPhases.captured; var listener = listenerAtPhase(domID, event, phase); if (listener) { - event._dispatchListeners = accumulate(event._dispatchListeners, listener); - event._dispatchIDs = accumulate(event._dispatchIDs, domID); + event._dispatchListeners = + accumulateInto(event._dispatchListeners, listener); + event._dispatchIDs = accumulateInto(event._dispatchIDs, domID); } } @@ -3492,8 +3467,9 @@ function accumulateDispatches(id, ignoredDirection, event) { var registrationName = event.dispatchConfig.registrationName; var listener = getListener(id, registrationName); if (listener) { - event._dispatchListeners = accumulate(event._dispatchListeners, listener); - event._dispatchIDs = accumulate(event._dispatchIDs, id); + event._dispatchListeners = + accumulateInto(event._dispatchListeners, listener); + event._dispatchIDs = accumulateInto(event._dispatchIDs, id); } } } @@ -3549,21 +3525,14 @@ var EventPropagators = { module.exports = EventPropagators; -},{"./EventConstants":16,"./EventPluginHub":18,"./accumulate":106,"./forEachAccumulated":121}],22:[function(_dereq_,module,exports){ +},{"./EventConstants":17,"./EventPluginHub":19,"./accumulateInto":109,"./forEachAccumulated":126}],23:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ExecutionEnvironment */ @@ -3601,21 +3570,14 @@ var ExecutionEnvironment = { module.exports = ExecutionEnvironment; -},{}],23:[function(_dereq_,module,exports){ +},{}],24:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule HTMLDOMPropertyConfig */ @@ -3660,6 +3622,7 @@ var HTMLDOMPropertyConfig = { * Standard Properties */ accept: null, + acceptCharset: null, accessKey: null, action: null, allowFullScreen: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, @@ -3674,6 +3637,7 @@ var HTMLDOMPropertyConfig = { cellSpacing: null, charSet: MUST_USE_ATTRIBUTE, checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, + classID: MUST_USE_ATTRIBUTE, // To set className on SVG elements, it's necessary to use .setAttribute; // this works on HTML elements too in all browsers except IE8. Conveniently, // IE8 doesn't support SVG and so we can simply use the attribute in @@ -3709,10 +3673,12 @@ var HTMLDOMPropertyConfig = { id: MUST_USE_PROPERTY, label: null, lang: null, - list: null, + list: MUST_USE_ATTRIBUTE, loop: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, + manifest: MUST_USE_ATTRIBUTE, max: null, maxLength: MUST_USE_ATTRIBUTE, + media: MUST_USE_ATTRIBUTE, mediaGroup: null, method: null, min: null, @@ -3720,6 +3686,7 @@ var HTMLDOMPropertyConfig = { muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, name: null, noValidate: HAS_BOOLEAN_VALUE, + open: null, pattern: null, placeholder: null, poster: null, @@ -3733,18 +3700,17 @@ var HTMLDOMPropertyConfig = { rowSpan: null, sandbox: null, scope: null, - scrollLeft: MUST_USE_PROPERTY, scrolling: null, - scrollTop: MUST_USE_PROPERTY, seamless: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, shape: null, size: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE, + sizes: MUST_USE_ATTRIBUTE, span: HAS_POSITIVE_NUMERIC_VALUE, spellCheck: null, src: null, srcDoc: MUST_USE_PROPERTY, - srcSet: null, + srcSet: MUST_USE_ATTRIBUTE, start: HAS_NUMERIC_VALUE, step: null, style: null, @@ -3768,6 +3734,7 @@ var HTMLDOMPropertyConfig = { property: null // Supports OG in meta tags }, DOMAttributeNames: { + acceptCharset: 'accept-charset', className: 'class', htmlFor: 'for', httpEquiv: 'http-equiv' @@ -3789,21 +3756,14 @@ var HTMLDOMPropertyConfig = { module.exports = HTMLDOMPropertyConfig; -},{"./DOMProperty":11,"./ExecutionEnvironment":22}],24:[function(_dereq_,module,exports){ +},{"./DOMProperty":12,"./ExecutionEnvironment":23}],25:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule LinkedStateMixin * @typechecks static-only @@ -3837,21 +3797,14 @@ var LinkedStateMixin = { module.exports = LinkedStateMixin; -},{"./ReactLink":65,"./ReactStateSetters":81}],25:[function(_dereq_,module,exports){ +},{"./ReactLink":68,"./ReactStateSetters":85}],26:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule LinkedValueUtils * @typechecks static-only @@ -3998,21 +3951,14 @@ var LinkedValueUtils = { module.exports = LinkedValueUtils; -},{"./ReactPropTypes":75,"./invariant":134}],26:[function(_dereq_,module,exports){ +},{"./ReactPropTypes":79,"./invariant":140}],27:[function(_dereq_,module,exports){ /** - * Copyright 2014 Facebook, Inc. + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule LocalEventTrapMixin */ @@ -4021,7 +3967,7 @@ module.exports = LinkedValueUtils; var ReactBrowserEventEmitter = _dereq_("./ReactBrowserEventEmitter"); -var accumulate = _dereq_("./accumulate"); +var accumulateInto = _dereq_("./accumulateInto"); var forEachAccumulated = _dereq_("./forEachAccumulated"); var invariant = _dereq_("./invariant"); @@ -4037,7 +3983,8 @@ var LocalEventTrapMixin = { handlerBaseName, this.getDOMNode() ); - this._localEventListeners = accumulate(this._localEventListeners, listener); + this._localEventListeners = + accumulateInto(this._localEventListeners, listener); }, // trapCapturedEvent would look nearly identical. We don't implement that @@ -4052,21 +3999,14 @@ var LocalEventTrapMixin = { module.exports = LocalEventTrapMixin; -},{"./ReactBrowserEventEmitter":31,"./accumulate":106,"./forEachAccumulated":121,"./invariant":134}],27:[function(_dereq_,module,exports){ +},{"./ReactBrowserEventEmitter":33,"./accumulateInto":109,"./forEachAccumulated":126,"./invariant":140}],28:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule MobileSafariClickEventPlugin * @typechecks static-only @@ -4117,21 +4057,61 @@ var MobileSafariClickEventPlugin = { module.exports = MobileSafariClickEventPlugin; -},{"./EventConstants":16,"./emptyFunction":116}],28:[function(_dereq_,module,exports){ +},{"./EventConstants":17,"./emptyFunction":121}],29:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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 + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * - * http://www.apache.org/licenses/LICENSE-2.0 + * @providesModule Object.assign + */ + +// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign + +function assign(target, sources) { + if (target == null) { + throw new TypeError('Object.assign target cannot be null or undefined'); + } + + var to = Object(target); + var hasOwnProperty = Object.prototype.hasOwnProperty; + + for (var nextIndex = 1; nextIndex < arguments.length; nextIndex++) { + var nextSource = arguments[nextIndex]; + if (nextSource == null) { + continue; + } + + var from = Object(nextSource); + + // We don't currently support accessors nor proxies. Therefore this + // copy cannot throw. If we ever supported this then we must handle + // exceptions and side-effects. We don't support symbols so they won't + // be transferred. + + for (var key in from) { + if (hasOwnProperty.call(from, key)) { + to[key] = from[key]; + } + } + } + + return to; +}; + +module.exports = assign; + +},{}],30:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule PooledClass */ @@ -4238,21 +4218,14 @@ var PooledClass = { module.exports = PooledClass; -},{"./invariant":134}],29:[function(_dereq_,module,exports){ +},{"./invariant":140}],31:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule React */ @@ -4266,11 +4239,13 @@ var ReactComponent = _dereq_("./ReactComponent"); var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); var ReactContext = _dereq_("./ReactContext"); var ReactCurrentOwner = _dereq_("./ReactCurrentOwner"); -var ReactDescriptor = _dereq_("./ReactDescriptor"); +var ReactElement = _dereq_("./ReactElement"); +var ReactElementValidator = _dereq_("./ReactElementValidator"); var ReactDOM = _dereq_("./ReactDOM"); var ReactDOMComponent = _dereq_("./ReactDOMComponent"); var ReactDefaultInjection = _dereq_("./ReactDefaultInjection"); var ReactInstanceHandles = _dereq_("./ReactInstanceHandles"); +var ReactLegacyElement = _dereq_("./ReactLegacyElement"); var ReactMount = _dereq_("./ReactMount"); var ReactMultiChild = _dereq_("./ReactMultiChild"); var ReactPerf = _dereq_("./ReactPerf"); @@ -4278,10 +4253,30 @@ var ReactPropTypes = _dereq_("./ReactPropTypes"); var ReactServerRendering = _dereq_("./ReactServerRendering"); var ReactTextComponent = _dereq_("./ReactTextComponent"); +var assign = _dereq_("./Object.assign"); +var deprecated = _dereq_("./deprecated"); var onlyChild = _dereq_("./onlyChild"); ReactDefaultInjection.inject(); +var createElement = ReactElement.createElement; +var createFactory = ReactElement.createFactory; + +if ("production" !== "development") { + createElement = ReactElementValidator.createElement; + createFactory = ReactElementValidator.createFactory; +} + +// TODO: Drop legacy elements once classes no longer export these factories +createElement = ReactLegacyElement.wrapCreateElement( + createElement +); +createFactory = ReactLegacyElement.wrapCreateFactory( + createFactory +); + +var render = ReactPerf.measure('React', 'render', ReactMount.render); + var React = { Children: { map: ReactChildren.map, @@ -4295,25 +4290,58 @@ var React = { EventPluginUtils.useTouchEvents = shouldUseTouch; }, createClass: ReactCompositeComponent.createClass, - createDescriptor: function(type, props, children) { - var args = Array.prototype.slice.call(arguments, 1); - return type.apply(null, args); - }, + createElement: createElement, + createFactory: createFactory, constructAndRenderComponent: ReactMount.constructAndRenderComponent, constructAndRenderComponentByID: ReactMount.constructAndRenderComponentByID, - renderComponent: ReactPerf.measure( + render: render, + renderToString: ReactServerRendering.renderToString, + renderToStaticMarkup: ReactServerRendering.renderToStaticMarkup, + unmountComponentAtNode: ReactMount.unmountComponentAtNode, + isValidClass: ReactLegacyElement.isValidClass, + isValidElement: ReactElement.isValidElement, + withContext: ReactContext.withContext, + + // Hook for JSX spread, don't use this for anything else. + __spread: assign, + + // Deprecations (remove for 0.13) + renderComponent: deprecated( 'React', 'renderComponent', - ReactMount.renderComponent + 'render', + this, + render ), - renderComponentToString: ReactServerRendering.renderComponentToString, - renderComponentToStaticMarkup: - ReactServerRendering.renderComponentToStaticMarkup, - unmountComponentAtNode: ReactMount.unmountComponentAtNode, - isValidClass: ReactDescriptor.isValidFactory, - isValidComponent: ReactDescriptor.isValidDescriptor, - withContext: ReactContext.withContext, - __internals: { + renderComponentToString: deprecated( + 'React', + 'renderComponentToString', + 'renderToString', + this, + ReactServerRendering.renderToString + ), + renderComponentToStaticMarkup: deprecated( + 'React', + 'renderComponentToStaticMarkup', + 'renderToStaticMarkup', + this, + ReactServerRendering.renderToStaticMarkup + ), + isValidComponent: deprecated( + 'React', + 'isValidComponent', + 'isValidElement', + this, + ReactElement.isValidElement + ) +}; + +// Inject the runtime into a devtools global hook regardless of browser. +// Allows for debugging when the hook is injected on the page. +if ( + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && + typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') { + __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({ Component: ReactComponent, CurrentOwner: ReactCurrentOwner, DOMComponent: ReactDOMComponent, @@ -4322,18 +4350,23 @@ var React = { Mount: ReactMount, MultiChild: ReactMultiChild, TextComponent: ReactTextComponent - } -}; + }); +} if ("production" !== "development") { var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); - if (ExecutionEnvironment.canUseDOM && - window.top === window.self && - navigator.userAgent.indexOf('Chrome') > -1) { - console.debug( - 'Download the React DevTools for a better development experience: ' + - 'http://fb.me/react-devtools' - ); + if (ExecutionEnvironment.canUseDOM && window.top === window.self) { + + // If we're in Chrome, look for the devtools marker and provide a download + // link if not installed. + if (navigator.userAgent.indexOf('Chrome') > -1) { + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') { + console.debug( + 'Download the React DevTools for a better development experience: ' + + 'http://fb.me/react-devtools' + ); + } + } var expectedFeatures = [ // shims @@ -4353,7 +4386,7 @@ if ("production" !== "development") { Object.freeze ]; - for (var i in expectedFeatures) { + for (var i = 0; i < expectedFeatures.length; i++) { if (!expectedFeatures[i]) { console.error( 'One or more ES5 shim/shams expected by React are not available: ' + @@ -4367,25 +4400,18 @@ if ("production" !== "development") { // Version exists only in the open-source version of React, not in Facebook's // internal version. -React.version = '0.11.1'; +React.version = '0.12.1'; module.exports = React; -},{"./DOMPropertyOperations":12,"./EventPluginUtils":20,"./ExecutionEnvironment":22,"./ReactChildren":34,"./ReactComponent":35,"./ReactCompositeComponent":38,"./ReactContext":39,"./ReactCurrentOwner":40,"./ReactDOM":41,"./ReactDOMComponent":43,"./ReactDefaultInjection":53,"./ReactDescriptor":56,"./ReactInstanceHandles":64,"./ReactMount":67,"./ReactMultiChild":68,"./ReactPerf":71,"./ReactPropTypes":75,"./ReactServerRendering":79,"./ReactTextComponent":83,"./onlyChild":149}],30:[function(_dereq_,module,exports){ +},{"./DOMPropertyOperations":13,"./EventPluginUtils":21,"./ExecutionEnvironment":23,"./Object.assign":29,"./ReactChildren":36,"./ReactComponent":37,"./ReactCompositeComponent":40,"./ReactContext":41,"./ReactCurrentOwner":42,"./ReactDOM":43,"./ReactDOMComponent":45,"./ReactDefaultInjection":55,"./ReactElement":58,"./ReactElementValidator":59,"./ReactInstanceHandles":66,"./ReactLegacyElement":67,"./ReactMount":70,"./ReactMultiChild":71,"./ReactPerf":75,"./ReactPropTypes":79,"./ReactServerRendering":83,"./ReactTextComponent":87,"./deprecated":120,"./onlyChild":151}],32:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactBrowserComponentMixin */ @@ -4419,21 +4445,14 @@ var ReactBrowserComponentMixin = { module.exports = ReactBrowserComponentMixin; -},{"./ReactEmptyComponent":58,"./ReactMount":67,"./invariant":134}],31:[function(_dereq_,module,exports){ +},{"./ReactEmptyComponent":60,"./ReactMount":70,"./invariant":140}],33:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactBrowserEventEmitter * @typechecks static-only @@ -4447,8 +4466,8 @@ var EventPluginRegistry = _dereq_("./EventPluginRegistry"); var ReactEventEmitterMixin = _dereq_("./ReactEventEmitterMixin"); var ViewportMetrics = _dereq_("./ViewportMetrics"); +var assign = _dereq_("./Object.assign"); var isEventSupported = _dereq_("./isEventSupported"); -var merge = _dereq_("./merge"); /** * Summary of `ReactBrowserEventEmitter` event handling: @@ -4577,7 +4596,7 @@ function getListeningForDocument(mountAt) { * * @internal */ -var ReactBrowserEventEmitter = merge(ReactEventEmitterMixin, { +var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin, { /** * Injectable event backend @@ -4781,21 +4800,14 @@ var ReactBrowserEventEmitter = merge(ReactEventEmitterMixin, { module.exports = ReactBrowserEventEmitter; -},{"./EventConstants":16,"./EventPluginHub":18,"./EventPluginRegistry":19,"./ReactEventEmitterMixin":60,"./ViewportMetrics":105,"./isEventSupported":135,"./merge":144}],32:[function(_dereq_,module,exports){ +},{"./EventConstants":17,"./EventPluginHub":19,"./EventPluginRegistry":20,"./Object.assign":29,"./ReactEventEmitterMixin":62,"./ViewportMetrics":108,"./isEventSupported":141}],34:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @typechecks * @providesModule ReactCSSTransitionGroup @@ -4805,8 +4817,14 @@ module.exports = ReactBrowserEventEmitter; var React = _dereq_("./React"); -var ReactTransitionGroup = _dereq_("./ReactTransitionGroup"); -var ReactCSSTransitionGroupChild = _dereq_("./ReactCSSTransitionGroupChild"); +var assign = _dereq_("./Object.assign"); + +var ReactTransitionGroup = React.createFactory( + _dereq_("./ReactTransitionGroup") +); +var ReactCSSTransitionGroupChild = React.createFactory( + _dereq_("./ReactCSSTransitionGroupChild") +); var ReactCSSTransitionGroup = React.createClass({ displayName: 'ReactCSSTransitionGroup', @@ -4839,10 +4857,9 @@ var ReactCSSTransitionGroup = React.createClass({ }, render: function() { - return this.transferPropsTo( + return ( ReactTransitionGroup( - {childFactory: this._wrapChild}, - this.props.children + assign({}, this.props, {childFactory: this._wrapChild}) ) ); } @@ -4850,21 +4867,14 @@ var ReactCSSTransitionGroup = React.createClass({ module.exports = ReactCSSTransitionGroup; -},{"./React":29,"./ReactCSSTransitionGroupChild":33,"./ReactTransitionGroup":86}],33:[function(_dereq_,module,exports){ +},{"./Object.assign":29,"./React":31,"./ReactCSSTransitionGroupChild":35,"./ReactTransitionGroup":90}],35:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @typechecks * @providesModule ReactCSSTransitionGroupChild @@ -4909,7 +4919,10 @@ var ReactCSSTransitionGroupChild = React.createClass({ var activeClassName = className + '-active'; var noEventTimeout = null; - var endListener = function() { + var endListener = function(e) { + if (e && e.target !== node) { + return; + } if ("production" !== "development") { clearTimeout(noEventTimeout); } @@ -4987,21 +5000,14 @@ var ReactCSSTransitionGroupChild = React.createClass({ module.exports = ReactCSSTransitionGroupChild; -},{"./CSSCore":3,"./React":29,"./ReactTransitionEvents":85,"./onlyChild":149}],34:[function(_dereq_,module,exports){ +},{"./CSSCore":4,"./React":31,"./ReactTransitionEvents":89,"./onlyChild":151}],36:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactChildren */ @@ -5142,34 +5148,27 @@ var ReactChildren = { module.exports = ReactChildren; -},{"./PooledClass":28,"./traverseAllChildren":156,"./warning":158}],35:[function(_dereq_,module,exports){ +},{"./PooledClass":30,"./traverseAllChildren":158,"./warning":160}],37:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactComponent */ "use strict"; -var ReactDescriptor = _dereq_("./ReactDescriptor"); +var ReactElement = _dereq_("./ReactElement"); var ReactOwner = _dereq_("./ReactOwner"); var ReactUpdates = _dereq_("./ReactUpdates"); +var assign = _dereq_("./Object.assign"); var invariant = _dereq_("./invariant"); var keyMirror = _dereq_("./keyMirror"); -var merge = _dereq_("./merge"); /** * Every React component is in one of these life cycles. @@ -5292,11 +5291,11 @@ var ReactComponent = { * @public */ setProps: function(partialProps, callback) { - // Merge with the pending descriptor if it exists, otherwise with existing - // descriptor props. - var descriptor = this._pendingDescriptor || this._descriptor; + // Merge with the pending element if it exists, otherwise with existing + // element props. + var element = this._pendingElement || this._currentElement; this.replaceProps( - merge(descriptor.props, partialProps), + assign({}, element.props, partialProps), callback ); }, @@ -5322,10 +5321,10 @@ var ReactComponent = { '`render` method to pass the correct value as props to the component ' + 'where it is created.' ) : invariant(this._mountDepth === 0)); - // This is a deoptimized path. We optimize for always having a descriptor. - // This creates an extra internal descriptor. - this._pendingDescriptor = ReactDescriptor.cloneAndReplaceProps( - this._pendingDescriptor || this._descriptor, + // This is a deoptimized path. We optimize for always having a element. + // This creates an extra internal element. + this._pendingElement = ReactElement.cloneAndReplaceProps( + this._pendingElement || this._currentElement, props ); ReactUpdates.enqueueUpdate(this, callback); @@ -5340,12 +5339,12 @@ var ReactComponent = { * @internal */ _setPropsInternal: function(partialProps, callback) { - // This is a deoptimized path. We optimize for always having a descriptor. - // This creates an extra internal descriptor. - var descriptor = this._pendingDescriptor || this._descriptor; - this._pendingDescriptor = ReactDescriptor.cloneAndReplaceProps( - descriptor, - merge(descriptor.props, partialProps) + // This is a deoptimized path. We optimize for always having a element. + // This creates an extra internal element. + var element = this._pendingElement || this._currentElement; + this._pendingElement = ReactElement.cloneAndReplaceProps( + element, + assign({}, element.props, partialProps) ); ReactUpdates.enqueueUpdate(this, callback); }, @@ -5356,19 +5355,19 @@ var ReactComponent = { * Subclasses that override this method should make sure to invoke * `ReactComponent.Mixin.construct.call(this, ...)`. * - * @param {ReactDescriptor} descriptor + * @param {ReactElement} element * @internal */ - construct: function(descriptor) { + construct: function(element) { // This is the public exposed props object after it has been processed - // with default props. The descriptor's props represents the true internal + // with default props. The element's props represents the true internal // state of the props. - this.props = descriptor.props; + this.props = element.props; // Record the component responsible for creating this component. - // This is accessible through the descriptor but we maintain an extra + // This is accessible through the element but we maintain an extra // field for compatibility with devtools and as a way to make an // incremental update. TODO: Consider deprecating this field. - this._owner = descriptor._owner; + this._owner = element._owner; // All components start unmounted. this._lifeCycleState = ComponentLifeCycle.UNMOUNTED; @@ -5376,10 +5375,10 @@ var ReactComponent = { // See ReactUpdates. this._pendingCallbacks = null; - // We keep the old descriptor and a reference to the pending descriptor + // We keep the old element and a reference to the pending element // to track updates. - this._descriptor = descriptor; - this._pendingDescriptor = null; + this._currentElement = element; + this._pendingElement = null; }, /** @@ -5404,10 +5403,10 @@ var ReactComponent = { 'single component instance in multiple places.', rootID ) : invariant(!this.isMounted())); - var props = this._descriptor.props; - if (props.ref != null) { - var owner = this._descriptor._owner; - ReactOwner.addComponentAsRefTo(this, props.ref, owner); + var ref = this._currentElement.ref; + if (ref != null) { + var owner = this._currentElement._owner; + ReactOwner.addComponentAsRefTo(this, ref, owner); } this._rootNodeID = rootID; this._lifeCycleState = ComponentLifeCycle.MOUNTED; @@ -5430,9 +5429,9 @@ var ReactComponent = { this.isMounted(), 'unmountComponent(): Can only unmount a mounted component.' ) : invariant(this.isMounted())); - var props = this.props; - if (props.ref != null) { - ReactOwner.removeComponentAsRefFrom(this, props.ref, this._owner); + var ref = this._currentElement.ref; + if (ref != null) { + ReactOwner.removeComponentAsRefFrom(this, ref, this._owner); } unmountIDFromEnvironment(this._rootNodeID); this._rootNodeID = null; @@ -5450,49 +5449,49 @@ var ReactComponent = { * @param {ReactReconcileTransaction} transaction * @internal */ - receiveComponent: function(nextDescriptor, transaction) { + receiveComponent: function(nextElement, transaction) { ("production" !== "development" ? invariant( this.isMounted(), 'receiveComponent(...): Can only update a mounted component.' ) : invariant(this.isMounted())); - this._pendingDescriptor = nextDescriptor; + this._pendingElement = nextElement; this.performUpdateIfNecessary(transaction); }, /** - * If `_pendingDescriptor` is set, update the component. + * If `_pendingElement` is set, update the component. * * @param {ReactReconcileTransaction} transaction * @internal */ performUpdateIfNecessary: function(transaction) { - if (this._pendingDescriptor == null) { + if (this._pendingElement == null) { return; } - var prevDescriptor = this._descriptor; - var nextDescriptor = this._pendingDescriptor; - this._descriptor = nextDescriptor; - this.props = nextDescriptor.props; - this._owner = nextDescriptor._owner; - this._pendingDescriptor = null; - this.updateComponent(transaction, prevDescriptor); + var prevElement = this._currentElement; + var nextElement = this._pendingElement; + this._currentElement = nextElement; + this.props = nextElement.props; + this._owner = nextElement._owner; + this._pendingElement = null; + this.updateComponent(transaction, prevElement); }, /** * Updates the component's currently mounted representation. * * @param {ReactReconcileTransaction} transaction - * @param {object} prevDescriptor + * @param {object} prevElement * @internal */ - updateComponent: function(transaction, prevDescriptor) { - var nextDescriptor = this._descriptor; + updateComponent: function(transaction, prevElement) { + var nextElement = this._currentElement; // If either the owner or a `ref` has changed, make sure the newest owner // has stored a reference to `this`, and the previous owner (if different) - // has forgotten the reference to `this`. We use the descriptor instead + // has forgotten the reference to `this`. We use the element instead // of the public this.props because the post processing cannot determine - // a ref. The ref conceptually lives on the descriptor. + // a ref. The ref conceptually lives on the element. // TODO: Should this even be possible? The owner cannot change because // it's forbidden by shouldUpdateReactComponent. The ref can change @@ -5500,19 +5499,19 @@ var ReactComponent = { // is made. It probably belongs where the key checking and // instantiateReactComponent is done. - if (nextDescriptor._owner !== prevDescriptor._owner || - nextDescriptor.props.ref !== prevDescriptor.props.ref) { - if (prevDescriptor.props.ref != null) { + if (nextElement._owner !== prevElement._owner || + nextElement.ref !== prevElement.ref) { + if (prevElement.ref != null) { ReactOwner.removeComponentAsRefFrom( - this, prevDescriptor.props.ref, prevDescriptor._owner + this, prevElement.ref, prevElement._owner ); } // Correct, even if the owner is the same, and only the ref has changed. - if (nextDescriptor.props.ref != null) { + if (nextElement.ref != null) { ReactOwner.addComponentAsRefTo( this, - nextDescriptor.props.ref, - nextDescriptor._owner + nextElement.ref, + nextElement._owner ); } } @@ -5526,7 +5525,7 @@ var ReactComponent = { * @param {boolean} shouldReuseMarkup If true, do not insert markup * @final * @internal - * @see {ReactMount.renderComponent} + * @see {ReactMount.render} */ mountComponentIntoNode: function(rootID, container, shouldReuseMarkup) { var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(); @@ -5590,21 +5589,14 @@ var ReactComponent = { module.exports = ReactComponent; -},{"./ReactDescriptor":56,"./ReactOwner":70,"./ReactUpdates":87,"./invariant":134,"./keyMirror":140,"./merge":144}],36:[function(_dereq_,module,exports){ +},{"./Object.assign":29,"./ReactElement":58,"./ReactOwner":74,"./ReactUpdates":91,"./invariant":140,"./keyMirror":146}],38:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactComponentBrowserEnvironment */ @@ -5717,21 +5709,14 @@ var ReactComponentBrowserEnvironment = { module.exports = ReactComponentBrowserEnvironment; -},{"./ReactDOMIDOperations":45,"./ReactMarkupChecksum":66,"./ReactMount":67,"./ReactPerf":71,"./ReactReconcileTransaction":77,"./getReactRootElementInContainer":128,"./invariant":134,"./setInnerHTML":152}],37:[function(_dereq_,module,exports){ +},{"./ReactDOMIDOperations":47,"./ReactMarkupChecksum":69,"./ReactMount":70,"./ReactPerf":75,"./ReactReconcileTransaction":81,"./getReactRootElementInContainer":134,"./invariant":140,"./setInnerHTML":154}],39:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactComponentWithPureRenderMixin */ @@ -5773,21 +5758,14 @@ var ReactComponentWithPureRenderMixin = { module.exports = ReactComponentWithPureRenderMixin; -},{"./shallowEqual":153}],38:[function(_dereq_,module,exports){ +},{"./shallowEqual":155}],40:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactCompositeComponent */ @@ -5797,10 +5775,11 @@ module.exports = ReactComponentWithPureRenderMixin; var ReactComponent = _dereq_("./ReactComponent"); var ReactContext = _dereq_("./ReactContext"); var ReactCurrentOwner = _dereq_("./ReactCurrentOwner"); -var ReactDescriptor = _dereq_("./ReactDescriptor"); -var ReactDescriptorValidator = _dereq_("./ReactDescriptorValidator"); +var ReactElement = _dereq_("./ReactElement"); +var ReactElementValidator = _dereq_("./ReactElementValidator"); var ReactEmptyComponent = _dereq_("./ReactEmptyComponent"); var ReactErrorUtils = _dereq_("./ReactErrorUtils"); +var ReactLegacyElement = _dereq_("./ReactLegacyElement"); var ReactOwner = _dereq_("./ReactOwner"); var ReactPerf = _dereq_("./ReactPerf"); var ReactPropTransferer = _dereq_("./ReactPropTransferer"); @@ -5808,16 +5787,18 @@ var ReactPropTypeLocations = _dereq_("./ReactPropTypeLocations"); var ReactPropTypeLocationNames = _dereq_("./ReactPropTypeLocationNames"); var ReactUpdates = _dereq_("./ReactUpdates"); +var assign = _dereq_("./Object.assign"); var instantiateReactComponent = _dereq_("./instantiateReactComponent"); var invariant = _dereq_("./invariant"); var keyMirror = _dereq_("./keyMirror"); -var merge = _dereq_("./merge"); -var mixInto = _dereq_("./mixInto"); +var keyOf = _dereq_("./keyOf"); var monitorCodeUse = _dereq_("./monitorCodeUse"); var mapObject = _dereq_("./mapObject"); var shouldUpdateReactComponent = _dereq_("./shouldUpdateReactComponent"); var warning = _dereq_("./warning"); +var MIXINS_KEY = keyOf({mixins: null}); + /** * Policies that describe methods in `ReactCompositeComponentInterface`. */ @@ -6121,7 +6102,8 @@ var RESERVED_SPEC_KEYS = { childContextTypes, ReactPropTypeLocations.childContext ); - Constructor.childContextTypes = merge( + Constructor.childContextTypes = assign( + {}, Constructor.childContextTypes, childContextTypes ); @@ -6132,7 +6114,11 @@ var RESERVED_SPEC_KEYS = { contextTypes, ReactPropTypeLocations.context ); - Constructor.contextTypes = merge(Constructor.contextTypes, contextTypes); + Constructor.contextTypes = assign( + {}, + Constructor.contextTypes, + contextTypes + ); }, /** * Special case getDefaultProps which should move into statics but requires @@ -6154,7 +6140,11 @@ var RESERVED_SPEC_KEYS = { propTypes, ReactPropTypeLocations.prop ); - Constructor.propTypes = merge(Constructor.propTypes, propTypes); + Constructor.propTypes = assign( + {}, + Constructor.propTypes, + propTypes + ); }, statics: function(Constructor, statics) { mixStaticSpecIntoComponent(Constructor, statics); @@ -6223,11 +6213,12 @@ function validateLifeCycleOnReplaceState(instance) { 'replaceState(...): Can only update a mounted or mounting component.' ) : invariant(instance.isMounted() || compositeLifeCycleState === CompositeLifeCycle.MOUNTING)); - ("production" !== "development" ? invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE, + ("production" !== "development" ? invariant( + ReactCurrentOwner.current == null, 'replaceState(...): Cannot update during an existing state transition ' + - '(such as within `render`). This could potentially cause an infinite ' + - 'loop so it is forbidden.' - ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE)); + '(such as within `render`). Render methods should be a pure function ' + + 'of props and state.' + ) : invariant(ReactCurrentOwner.current == null)); ("production" !== "development" ? invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING, 'replaceState(...): Cannot update while unmounting component. This ' + 'usually means you called setState() on an unmounted component.' @@ -6235,28 +6226,45 @@ function validateLifeCycleOnReplaceState(instance) { } /** - * Custom version of `mixInto` which handles policy validation and reserved + * Mixin helper which handles policy validation and reserved * specification keys when building `ReactCompositeComponent` classses. */ function mixSpecIntoComponent(Constructor, spec) { + if (!spec) { + return; + } + ("production" !== "development" ? invariant( - !ReactDescriptor.isValidFactory(spec), + !ReactLegacyElement.isValidFactory(spec), 'ReactCompositeComponent: You\'re attempting to ' + 'use a component class as a mixin. Instead, just use a regular object.' - ) : invariant(!ReactDescriptor.isValidFactory(spec))); + ) : invariant(!ReactLegacyElement.isValidFactory(spec))); ("production" !== "development" ? invariant( - !ReactDescriptor.isValidDescriptor(spec), + !ReactElement.isValidElement(spec), 'ReactCompositeComponent: You\'re attempting to ' + 'use a component as a mixin. Instead, just use a regular object.' - ) : invariant(!ReactDescriptor.isValidDescriptor(spec))); + ) : invariant(!ReactElement.isValidElement(spec))); var proto = Constructor.prototype; + + // By handling mixins before any other properties, we ensure the same + // chaining order is applied to methods with DEFINE_MANY policy, whether + // mixins are listed before or after these methods in the spec. + if (spec.hasOwnProperty(MIXINS_KEY)) { + RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins); + } + for (var name in spec) { - var property = spec[name]; if (!spec.hasOwnProperty(name)) { continue; } + if (name === MIXINS_KEY) { + // We have already handled mixins in a special case above + continue; + } + + var property = spec[name]; validateMethodOverride(proto, name); if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) { @@ -6334,23 +6342,25 @@ function mixStaticSpecIntoComponent(Constructor, statics) { continue; } + var isReserved = name in RESERVED_SPEC_KEYS; + ("production" !== "development" ? invariant( + !isReserved, + 'ReactCompositeComponent: You are attempting to define a reserved ' + + 'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' + + 'as an instance property instead; it will still be accessible on the ' + + 'constructor.', + name + ) : invariant(!isReserved)); + var isInherited = name in Constructor; - var result = property; - if (isInherited) { - var existingProperty = Constructor[name]; - var existingType = typeof existingProperty; - var propertyType = typeof property; - ("production" !== "development" ? invariant( - existingType === 'function' && propertyType === 'function', - 'ReactCompositeComponent: You are attempting to define ' + - '`%s` on your component more than once, but that is only supported ' + - 'for functions, which are chained together. This conflict may be ' + - 'due to a mixin.', - name - ) : invariant(existingType === 'function' && propertyType === 'function')); - result = createChainedFunction(existingProperty, property); - } - Constructor[name] = result; + ("production" !== "development" ? invariant( + !isInherited, + 'ReactCompositeComponent: You are attempting to define ' + + '`%s` on your component more than once. This conflict may be ' + + 'due to a mixin.', + name + ) : invariant(!isInherited)); + Constructor[name] = property; } } @@ -6371,7 +6381,10 @@ function mergeObjectsWithNoDuplicateKeys(one, two) { ("production" !== "development" ? invariant( one[key] === undefined, 'mergeObjectsWithNoDuplicateKeys(): ' + - 'Tried to merge two objects with the same key: %s', + 'Tried to merge two objects with the same key: `%s`. This conflict ' + + 'may be due to a mixin; in particular, this may be caused by two ' + + 'getInitialState() or getDefaultProps() methods returning objects ' + + 'with clashing keys.', key ) : invariant(one[key] === undefined)); one[key] = value; @@ -6427,19 +6440,19 @@ function createChainedFunction(one, two) { * Top Row: ReactComponent.ComponentLifeCycle * Low Row: ReactComponent.CompositeLifeCycle * - * +-------+------------------------------------------------------+--------+ - * | UN | MOUNTED | UN | - * |MOUNTED| | MOUNTED| - * +-------+------------------------------------------------------+--------+ - * | ^--------+ +------+ +------+ +------+ +--------^ | - * | | | | | | | | | | | | - * | 0--|MOUNTING|-0-|RECEIV|-0-|RECEIV|-0-|RECEIV|-0-| UN |--->0 | - * | | | |PROPS | | PROPS| | STATE| |MOUNTING| | - * | | | | | | | | | | | | - * | | | | | | | | | | | | - * | +--------+ +------+ +------+ +------+ +--------+ | - * | | | | - * +-------+------------------------------------------------------+--------+ + * +-------+---------------------------------+--------+ + * | UN | MOUNTED | UN | + * |MOUNTED| | MOUNTED| + * +-------+---------------------------------+--------+ + * | ^--------+ +-------+ +--------^ | + * | | | | | | | | + * | 0--|MOUNTING|-0-|RECEIVE|-0-| UN |--->0 | + * | | | |PROPS | |MOUNTING| | + * | | | | | | | | + * | | | | | | | | + * | +--------+ +-------+ +--------+ | + * | | | | + * +-------+---------------------------------+--------+ */ var CompositeLifeCycle = keyMirror({ /** @@ -6456,12 +6469,7 @@ var CompositeLifeCycle = keyMirror({ * Components that are mounted and receiving new props respond to state * changes differently. */ - RECEIVING_PROPS: null, - /** - * Components that are mounted and receiving new state are guarded against - * additional state changes. - */ - RECEIVING_STATE: null + RECEIVING_PROPS: null }); /** @@ -6472,11 +6480,11 @@ var ReactCompositeComponentMixin = { /** * Base constructor for all composite component. * - * @param {ReactDescriptor} descriptor + * @param {ReactElement} element * @final * @internal */ - construct: function(descriptor) { + construct: function(element) { // Children can be either an array or more than one argument ReactComponent.Mixin.construct.apply(this, arguments); ReactOwner.Mixin.construct.apply(this, arguments); @@ -6485,7 +6493,7 @@ var ReactCompositeComponentMixin = { this._pendingState = null; // This is the public post-processed context. The real context and pending - // context lives on the descriptor. + // context lives on the element. this.context = null; this._compositeLifeCycleState = null; @@ -6528,7 +6536,7 @@ var ReactCompositeComponentMixin = { this._bindAutoBindMethods(); } - this.context = this._processContext(this._descriptor._context); + this.context = this._processContext(this._currentElement._context); this.props = this._processProps(this.props); this.state = this.getInitialState ? this.getInitialState() : null; @@ -6552,7 +6560,8 @@ var ReactCompositeComponentMixin = { } this._renderedComponent = instantiateReactComponent( - this._renderValidatedComponent() + this._renderValidatedComponent(), + this._currentElement.type // The wrapping type ); // Done with mounting, `setState` will now trigger UI changes. @@ -6624,7 +6633,7 @@ var ReactCompositeComponentMixin = { } // Merge with `_pendingState` if it exists, otherwise with existing state. this.replaceState( - merge(this._pendingState || this.state, partialState), + assign({}, this._pendingState || this.state, partialState), callback ); }, @@ -6712,7 +6721,7 @@ var ReactCompositeComponentMixin = { name ) : invariant(name in this.constructor.childContextTypes)); } - return merge(currentContext, childContext); + return assign({}, currentContext, childContext); } return currentContext; }, @@ -6727,25 +6736,13 @@ var ReactCompositeComponentMixin = { * @private */ _processProps: function(newProps) { - var defaultProps = this.constructor.defaultProps; - var props; - if (defaultProps) { - props = merge(newProps); - for (var propName in defaultProps) { - if (typeof props[propName] === 'undefined') { - props[propName] = defaultProps[propName]; - } - } - } else { - props = newProps; - } if ("production" !== "development") { var propTypes = this.constructor.propTypes; if (propTypes) { - this._checkPropTypes(propTypes, props, ReactPropTypeLocations.prop); + this._checkPropTypes(propTypes, newProps, ReactPropTypeLocations.prop); } } - return props; + return newProps; }, /** @@ -6757,7 +6754,7 @@ var ReactCompositeComponentMixin = { * @private */ _checkPropTypes: function(propTypes, props, location) { - // TODO: Stop validating prop types here and only use the descriptor + // TODO: Stop validating prop types here and only use the element // validation. var componentName = this.constructor.displayName; for (var propName in propTypes) { @@ -6776,7 +6773,7 @@ var ReactCompositeComponentMixin = { }, /** - * If any of `_pendingDescriptor`, `_pendingState`, or `_pendingForceUpdate` + * If any of `_pendingElement`, `_pendingState`, or `_pendingForceUpdate` * is set, update the component. * * @param {ReactReconcileTransaction} transaction @@ -6791,7 +6788,7 @@ var ReactCompositeComponentMixin = { return; } - if (this._pendingDescriptor == null && + if (this._pendingElement == null && this._pendingState == null && !this._pendingForceUpdate) { return; @@ -6799,12 +6796,12 @@ var ReactCompositeComponentMixin = { var nextContext = this.context; var nextProps = this.props; - var nextDescriptor = this._descriptor; - if (this._pendingDescriptor != null) { - nextDescriptor = this._pendingDescriptor; - nextContext = this._processContext(nextDescriptor._context); - nextProps = this._processProps(nextDescriptor.props); - this._pendingDescriptor = null; + var nextElement = this._currentElement; + if (this._pendingElement != null) { + nextElement = this._pendingElement; + nextContext = this._processContext(nextElement._context); + nextProps = this._processProps(nextElement.props); + this._pendingElement = null; this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS; if (this.componentWillReceiveProps) { @@ -6812,51 +6809,47 @@ var ReactCompositeComponentMixin = { } } - this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE; + this._compositeLifeCycleState = null; var nextState = this._pendingState || this.state; this._pendingState = null; - try { - var shouldUpdate = - this._pendingForceUpdate || - !this.shouldComponentUpdate || - this.shouldComponentUpdate(nextProps, nextState, nextContext); - - if ("production" !== "development") { - if (typeof shouldUpdate === "undefined") { - console.warn( - (this.constructor.displayName || 'ReactCompositeComponent') + - '.shouldComponentUpdate(): Returned undefined instead of a ' + - 'boolean value. Make sure to return true or false.' - ); - } - } + var shouldUpdate = + this._pendingForceUpdate || + !this.shouldComponentUpdate || + this.shouldComponentUpdate(nextProps, nextState, nextContext); - if (shouldUpdate) { - this._pendingForceUpdate = false; - // Will set `this.props`, `this.state` and `this.context`. - this._performComponentUpdate( - nextDescriptor, - nextProps, - nextState, - nextContext, - transaction + if ("production" !== "development") { + if (typeof shouldUpdate === "undefined") { + console.warn( + (this.constructor.displayName || 'ReactCompositeComponent') + + '.shouldComponentUpdate(): Returned undefined instead of a ' + + 'boolean value. Make sure to return true or false.' ); - } else { - // If it's determined that a component should not update, we still want - // to set props and state. - this._descriptor = nextDescriptor; - this.props = nextProps; - this.state = nextState; - this.context = nextContext; - - // Owner cannot change because shouldUpdateReactComponent doesn't allow - // it. TODO: Remove this._owner completely. - this._owner = nextDescriptor._owner; } - } finally { - this._compositeLifeCycleState = null; + } + + if (shouldUpdate) { + this._pendingForceUpdate = false; + // Will set `this.props`, `this.state` and `this.context`. + this._performComponentUpdate( + nextElement, + nextProps, + nextState, + nextContext, + transaction + ); + } else { + // If it's determined that a component should not update, we still want + // to set props and state. + this._currentElement = nextElement; + this.props = nextProps; + this.state = nextState; + this.context = nextContext; + + // Owner cannot change because shouldUpdateReactComponent doesn't allow + // it. TODO: Remove this._owner completely. + this._owner = nextElement._owner; } }, @@ -6864,7 +6857,7 @@ var ReactCompositeComponentMixin = { * Merges new props and state, notifies delegate methods of update and * performs update. * - * @param {ReactDescriptor} nextDescriptor Next descriptor + * @param {ReactElement} nextElement Next element * @param {object} nextProps Next public object to set as properties. * @param {?object} nextState Next object to set as state. * @param {?object} nextContext Next public object to set as context. @@ -6872,13 +6865,13 @@ var ReactCompositeComponentMixin = { * @private */ _performComponentUpdate: function( - nextDescriptor, + nextElement, nextProps, nextState, nextContext, transaction ) { - var prevDescriptor = this._descriptor; + var prevElement = this._currentElement; var prevProps = this.props; var prevState = this.state; var prevContext = this.context; @@ -6887,18 +6880,18 @@ var ReactCompositeComponentMixin = { this.componentWillUpdate(nextProps, nextState, nextContext); } - this._descriptor = nextDescriptor; + this._currentElement = nextElement; this.props = nextProps; this.state = nextState; this.context = nextContext; // Owner cannot change because shouldUpdateReactComponent doesn't allow // it. TODO: Remove this._owner completely. - this._owner = nextDescriptor._owner; + this._owner = nextElement._owner; this.updateComponent( transaction, - prevDescriptor + prevElement ); if (this.componentDidUpdate) { @@ -6909,22 +6902,22 @@ var ReactCompositeComponentMixin = { } }, - receiveComponent: function(nextDescriptor, transaction) { - if (nextDescriptor === this._descriptor && - nextDescriptor._owner != null) { - // Since descriptors are immutable after the owner is rendered, + receiveComponent: function(nextElement, transaction) { + if (nextElement === this._currentElement && + nextElement._owner != null) { + // Since elements are immutable after the owner is rendered, // we can do a cheap identity compare here to determine if this is a // superfluous reconcile. It's possible for state to be mutable but such // change should trigger an update of the owner which would recreate - // the descriptor. We explicitly check for the existence of an owner since - // it's possible for a descriptor created outside a composite to be + // the element. We explicitly check for the existence of an owner since + // it's possible for a element created outside a composite to be // deeply mutated and reused. return; } ReactComponent.Mixin.receiveComponent.call( this, - nextDescriptor, + nextElement, transaction ); }, @@ -6936,31 +6929,34 @@ var ReactCompositeComponentMixin = { * Sophisticated clients may wish to override this. * * @param {ReactReconcileTransaction} transaction - * @param {ReactDescriptor} prevDescriptor + * @param {ReactElement} prevElement * @internal * @overridable */ updateComponent: ReactPerf.measure( 'ReactCompositeComponent', 'updateComponent', - function(transaction, prevParentDescriptor) { + function(transaction, prevParentElement) { ReactComponent.Mixin.updateComponent.call( this, transaction, - prevParentDescriptor + prevParentElement ); var prevComponentInstance = this._renderedComponent; - var prevDescriptor = prevComponentInstance._descriptor; - var nextDescriptor = this._renderValidatedComponent(); - if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) { - prevComponentInstance.receiveComponent(nextDescriptor, transaction); + var prevElement = prevComponentInstance._currentElement; + var nextElement = this._renderValidatedComponent(); + if (shouldUpdateReactComponent(prevElement, nextElement)) { + prevComponentInstance.receiveComponent(nextElement, transaction); } else { // These two IDs are actually the same! But nothing should rely on that. var thisID = this._rootNodeID; var prevComponentID = prevComponentInstance._rootNodeID; prevComponentInstance.unmountComponent(); - this._renderedComponent = instantiateReactComponent(nextDescriptor); + this._renderedComponent = instantiateReactComponent( + nextElement, + this._currentElement.type + ); var nextMarkup = this._renderedComponent.mountComponent( thisID, transaction, @@ -6998,12 +6994,12 @@ var ReactCompositeComponentMixin = { ) : invariant(this.isMounted() || compositeLifeCycleState === CompositeLifeCycle.MOUNTING)); ("production" !== "development" ? invariant( - compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE && - compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING, + compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING && + ReactCurrentOwner.current == null, 'forceUpdate(...): Cannot force an update while unmounting component ' + - 'or during an existing state transition (such as within `render`).' - ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE && - compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING)); + 'or within a `render` function.' + ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING && + ReactCurrentOwner.current == null)); this._pendingForceUpdate = true; ReactUpdates.enqueueUpdate(this, callback); }, @@ -7018,7 +7014,7 @@ var ReactCompositeComponentMixin = { var renderedComponent; var previousContext = ReactContext.current; ReactContext.current = this._processChildContext( - this._descriptor._context + this._currentElement._context ); ReactCurrentOwner.current = this; try { @@ -7034,11 +7030,11 @@ var ReactCompositeComponentMixin = { ReactCurrentOwner.current = null; } ("production" !== "development" ? invariant( - ReactDescriptor.isValidDescriptor(renderedComponent), + ReactElement.isValidElement(renderedComponent), '%s.render(): A valid ReactComponent must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', this.constructor.displayName || 'ReactCompositeComponent' - ) : invariant(ReactDescriptor.isValidDescriptor(renderedComponent))); + ) : invariant(ReactElement.isValidElement(renderedComponent))); return renderedComponent; } ), @@ -7067,16 +7063,14 @@ var ReactCompositeComponentMixin = { */ _bindAutoBindMethod: function(method) { var component = this; - var boundMethod = function() { - return method.apply(component, arguments); - }; + var boundMethod = method.bind(component); if ("production" !== "development") { boundMethod.__reactBoundContext = component; boundMethod.__reactBoundMethod = method; boundMethod.__reactBoundArguments = null; var componentName = component.constructor.displayName; var _bind = boundMethod.bind; - boundMethod.bind = function(newThis ) {var args=Array.prototype.slice.call(arguments,1); + boundMethod.bind = function(newThis ) {for (var args=[],$__0=1,$__1=arguments.length;$__0<$__1;$__0++) args.push(arguments[$__0]); // User is trying to bind() an autobound method; we effectively will // ignore the value of "this" that the user is trying to use, so // let's warn. @@ -7107,10 +7101,13 @@ var ReactCompositeComponentMixin = { }; var ReactCompositeComponentBase = function() {}; -mixInto(ReactCompositeComponentBase, ReactComponent.Mixin); -mixInto(ReactCompositeComponentBase, ReactOwner.Mixin); -mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin); -mixInto(ReactCompositeComponentBase, ReactCompositeComponentMixin); +assign( + ReactCompositeComponentBase.prototype, + ReactComponent.Mixin, + ReactOwner.Mixin, + ReactPropTransferer.Mixin, + ReactCompositeComponentMixin +); /** * Module for creating composite components. @@ -7134,8 +7131,10 @@ var ReactCompositeComponent = { * @public */ createClass: function(spec) { - var Constructor = function(props, owner) { - this.construct(props, owner); + var Constructor = function(props) { + // This constructor is overridden by mocks. The argument is used + // by mocks to assert on what gets mounted. This will later be used + // by the stand-alone class implementation. }; Constructor.prototype = new ReactCompositeComponentBase(); Constructor.prototype.constructor = Constructor; @@ -7178,17 +7177,14 @@ var ReactCompositeComponent = { } } - var descriptorFactory = ReactDescriptor.createFactory(Constructor); - if ("production" !== "development") { - return ReactDescriptorValidator.createFactory( - descriptorFactory, - Constructor.propTypes, - Constructor.contextTypes + return ReactLegacyElement.wrapFactory( + ReactElementValidator.createFactory(Constructor) ); } - - return descriptorFactory; + return ReactLegacyElement.wrapFactory( + ReactElement.createFactory(Constructor) + ); }, injection: { @@ -7200,28 +7196,21 @@ var ReactCompositeComponent = { module.exports = ReactCompositeComponent; -},{"./ReactComponent":35,"./ReactContext":39,"./ReactCurrentOwner":40,"./ReactDescriptor":56,"./ReactDescriptorValidator":57,"./ReactEmptyComponent":58,"./ReactErrorUtils":59,"./ReactOwner":70,"./ReactPerf":71,"./ReactPropTransferer":72,"./ReactPropTypeLocationNames":73,"./ReactPropTypeLocations":74,"./ReactUpdates":87,"./instantiateReactComponent":133,"./invariant":134,"./keyMirror":140,"./mapObject":142,"./merge":144,"./mixInto":147,"./monitorCodeUse":148,"./shouldUpdateReactComponent":154,"./warning":158}],39:[function(_dereq_,module,exports){ +},{"./Object.assign":29,"./ReactComponent":37,"./ReactContext":41,"./ReactCurrentOwner":42,"./ReactElement":58,"./ReactElementValidator":59,"./ReactEmptyComponent":60,"./ReactErrorUtils":61,"./ReactLegacyElement":67,"./ReactOwner":74,"./ReactPerf":75,"./ReactPropTransferer":76,"./ReactPropTypeLocationNames":77,"./ReactPropTypeLocations":78,"./ReactUpdates":91,"./instantiateReactComponent":139,"./invariant":140,"./keyMirror":146,"./keyOf":147,"./mapObject":148,"./monitorCodeUse":150,"./shouldUpdateReactComponent":156,"./warning":160}],41:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactContext */ "use strict"; -var merge = _dereq_("./merge"); +var assign = _dereq_("./Object.assign"); /** * Keeps track of the current context. @@ -7243,7 +7232,7 @@ var ReactContext = { * A typical use case might look like * * render: function() { - * var children = ReactContext.withContext({foo: 'foo'} () => ( + * var children = ReactContext.withContext({foo: 'foo'}, () => ( * * )); * return <div>{children}</div>; @@ -7256,7 +7245,7 @@ var ReactContext = { withContext: function(newContext, scopedCallback) { var result; var previousContext = ReactContext.current; - ReactContext.current = merge(previousContext, newContext); + ReactContext.current = assign({}, previousContext, newContext); try { result = scopedCallback(); } finally { @@ -7269,21 +7258,14 @@ var ReactContext = { module.exports = ReactContext; -},{"./merge":144}],40:[function(_dereq_,module,exports){ +},{"./Object.assign":29}],42:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactCurrentOwner */ @@ -7310,21 +7292,14 @@ var ReactCurrentOwner = { module.exports = ReactCurrentOwner; -},{}],41:[function(_dereq_,module,exports){ +},{}],43:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDOM * @typechecks static-only @@ -7332,45 +7307,27 @@ module.exports = ReactCurrentOwner; "use strict"; -var ReactDescriptor = _dereq_("./ReactDescriptor"); -var ReactDescriptorValidator = _dereq_("./ReactDescriptorValidator"); -var ReactDOMComponent = _dereq_("./ReactDOMComponent"); +var ReactElement = _dereq_("./ReactElement"); +var ReactElementValidator = _dereq_("./ReactElementValidator"); +var ReactLegacyElement = _dereq_("./ReactLegacyElement"); -var mergeInto = _dereq_("./mergeInto"); var mapObject = _dereq_("./mapObject"); /** - * Creates a new React class that is idempotent and capable of containing other - * React components. It accepts event listeners and DOM properties that are - * valid according to `DOMProperty`. - * - * - Event listeners: `onClick`, `onMouseDown`, etc. - * - DOM properties: `className`, `name`, `title`, etc. - * - * The `style` property functions differently from the DOM API. It accepts an - * object mapping of style properties to values. + * Create a factory that creates HTML tag elements. * - * @param {boolean} omitClose True if the close tag should be omitted. * @param {string} tag Tag name (e.g. `div`). * @private */ -function createDOMComponentClass(omitClose, tag) { - var Constructor = function(descriptor) { - this.construct(descriptor); - }; - Constructor.prototype = new ReactDOMComponent(tag, omitClose); - Constructor.prototype.constructor = Constructor; - Constructor.displayName = tag; - - var ConvenienceConstructor = ReactDescriptor.createFactory(Constructor); - +function createDOMFactory(tag) { if ("production" !== "development") { - return ReactDescriptorValidator.createFactory( - ConvenienceConstructor + return ReactLegacyElement.markNonLegacyFactory( + ReactElementValidator.createFactory(tag) ); } - - return ConvenienceConstructor; + return ReactLegacyElement.markNonLegacyFactory( + ReactElement.createFactory(tag) + ); } /** @@ -7380,162 +7337,150 @@ function createDOMComponentClass(omitClose, tag) { * @public */ var ReactDOM = mapObject({ - a: false, - abbr: false, - address: false, - area: true, - article: false, - aside: false, - audio: false, - b: false, - base: true, - bdi: false, - bdo: false, - big: false, - blockquote: false, - body: false, - br: true, - button: false, - canvas: false, - caption: false, - cite: false, - code: false, - col: true, - colgroup: false, - data: false, - datalist: false, - dd: false, - del: false, - details: false, - dfn: false, - div: false, - dl: false, - dt: false, - em: false, - embed: true, - fieldset: false, - figcaption: false, - figure: false, - footer: false, - form: false, // NOTE: Injected, see `ReactDOMForm`. - h1: false, - h2: false, - h3: false, - h4: false, - h5: false, - h6: false, - head: false, - header: false, - hr: true, - html: false, - i: false, - iframe: false, - img: true, - input: true, - ins: false, - kbd: false, - keygen: true, - label: false, - legend: false, - li: false, - link: true, - main: false, - map: false, - mark: false, - menu: false, - menuitem: false, // NOTE: Close tag should be omitted, but causes problems. - meta: true, - meter: false, - nav: false, - noscript: false, - object: false, - ol: false, - optgroup: false, - option: false, - output: false, - p: false, - param: true, - pre: false, - progress: false, - q: false, - rp: false, - rt: false, - ruby: false, - s: false, - samp: false, - script: false, - section: false, - select: false, - small: false, - source: true, - span: false, - strong: false, - style: false, - sub: false, - summary: false, - sup: false, - table: false, - tbody: false, - td: false, - textarea: false, // NOTE: Injected, see `ReactDOMTextarea`. - tfoot: false, - th: false, - thead: false, - time: false, - title: false, - tr: false, - track: true, - u: false, - ul: false, - 'var': false, - video: false, - wbr: true, + a: 'a', + abbr: 'abbr', + address: 'address', + area: 'area', + article: 'article', + aside: 'aside', + audio: 'audio', + b: 'b', + base: 'base', + bdi: 'bdi', + bdo: 'bdo', + big: 'big', + blockquote: 'blockquote', + body: 'body', + br: 'br', + button: 'button', + canvas: 'canvas', + caption: 'caption', + cite: 'cite', + code: 'code', + col: 'col', + colgroup: 'colgroup', + data: 'data', + datalist: 'datalist', + dd: 'dd', + del: 'del', + details: 'details', + dfn: 'dfn', + dialog: 'dialog', + div: 'div', + dl: 'dl', + dt: 'dt', + em: 'em', + embed: 'embed', + fieldset: 'fieldset', + figcaption: 'figcaption', + figure: 'figure', + footer: 'footer', + form: 'form', + h1: 'h1', + h2: 'h2', + h3: 'h3', + h4: 'h4', + h5: 'h5', + h6: 'h6', + head: 'head', + header: 'header', + hr: 'hr', + html: 'html', + i: 'i', + iframe: 'iframe', + img: 'img', + input: 'input', + ins: 'ins', + kbd: 'kbd', + keygen: 'keygen', + label: 'label', + legend: 'legend', + li: 'li', + link: 'link', + main: 'main', + map: 'map', + mark: 'mark', + menu: 'menu', + menuitem: 'menuitem', + meta: 'meta', + meter: 'meter', + nav: 'nav', + noscript: 'noscript', + object: 'object', + ol: 'ol', + optgroup: 'optgroup', + option: 'option', + output: 'output', + p: 'p', + param: 'param', + picture: 'picture', + pre: 'pre', + progress: 'progress', + q: 'q', + rp: 'rp', + rt: 'rt', + ruby: 'ruby', + s: 's', + samp: 'samp', + script: 'script', + section: 'section', + select: 'select', + small: 'small', + source: 'source', + span: 'span', + strong: 'strong', + style: 'style', + sub: 'sub', + summary: 'summary', + sup: 'sup', + table: 'table', + tbody: 'tbody', + td: 'td', + textarea: 'textarea', + tfoot: 'tfoot', + th: 'th', + thead: 'thead', + time: 'time', + title: 'title', + tr: 'tr', + track: 'track', + u: 'u', + ul: 'ul', + 'var': 'var', + video: 'video', + wbr: 'wbr', // SVG - circle: false, - defs: false, - ellipse: false, - g: false, - line: false, - linearGradient: false, - mask: false, - path: false, - pattern: false, - polygon: false, - polyline: false, - radialGradient: false, - rect: false, - stop: false, - svg: false, - text: false, - tspan: false -}, createDOMComponentClass); - -var injection = { - injectComponentClasses: function(componentClasses) { - mergeInto(ReactDOM, componentClasses); - } -}; - -ReactDOM.injection = injection; + circle: 'circle', + defs: 'defs', + ellipse: 'ellipse', + g: 'g', + line: 'line', + linearGradient: 'linearGradient', + mask: 'mask', + path: 'path', + pattern: 'pattern', + polygon: 'polygon', + polyline: 'polyline', + radialGradient: 'radialGradient', + rect: 'rect', + stop: 'stop', + svg: 'svg', + text: 'text', + tspan: 'tspan' + +}, createDOMFactory); module.exports = ReactDOM; -},{"./ReactDOMComponent":43,"./ReactDescriptor":56,"./ReactDescriptorValidator":57,"./mapObject":142,"./mergeInto":146}],42:[function(_dereq_,module,exports){ +},{"./ReactElement":58,"./ReactElementValidator":59,"./ReactLegacyElement":67,"./mapObject":148}],44:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDOMButton */ @@ -7545,12 +7490,13 @@ module.exports = ReactDOM; var AutoFocusMixin = _dereq_("./AutoFocusMixin"); var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); +var ReactElement = _dereq_("./ReactElement"); var ReactDOM = _dereq_("./ReactDOM"); var keyMirror = _dereq_("./keyMirror"); -// Store a reference to the <button> `ReactDOMComponent`. -var button = ReactDOM.button; +// Store a reference to the <button> `ReactDOMComponent`. TODO: use string +var button = ReactElement.createFactory(ReactDOM.button.type); var mouseListenerNames = keyMirror({ onClick: true, @@ -7592,21 +7538,14 @@ var ReactDOMButton = ReactCompositeComponent.createClass({ module.exports = ReactDOMButton; -},{"./AutoFocusMixin":1,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./keyMirror":140}],43:[function(_dereq_,module,exports){ +},{"./AutoFocusMixin":2,"./ReactBrowserComponentMixin":32,"./ReactCompositeComponent":40,"./ReactDOM":43,"./ReactElement":58,"./keyMirror":146}],45:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDOMComponent * @typechecks static-only @@ -7624,11 +7563,12 @@ var ReactMount = _dereq_("./ReactMount"); var ReactMultiChild = _dereq_("./ReactMultiChild"); var ReactPerf = _dereq_("./ReactPerf"); +var assign = _dereq_("./Object.assign"); var escapeTextForBrowser = _dereq_("./escapeTextForBrowser"); var invariant = _dereq_("./invariant"); +var isEventSupported = _dereq_("./isEventSupported"); var keyOf = _dereq_("./keyOf"); -var merge = _dereq_("./merge"); -var mixInto = _dereq_("./mixInto"); +var monitorCodeUse = _dereq_("./monitorCodeUse"); var deleteListener = ReactBrowserEventEmitter.deleteListener; var listenTo = ReactBrowserEventEmitter.listenTo; @@ -7653,6 +7593,16 @@ function assertValidProps(props) { props.children == null || props.dangerouslySetInnerHTML == null, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.' ) : invariant(props.children == null || props.dangerouslySetInnerHTML == null)); + if ("production" !== "development") { + if (props.contentEditable && props.children != null) { + console.warn( + 'A component is `contentEditable` and contains `children` managed by ' + + 'React. It is now your responsibility to guarantee that none of those '+ + 'nodes are unexpectedly modified or duplicated. This is probably not ' + + 'intentional.' + ); + } + } ("production" !== "development" ? invariant( props.style == null || typeof props.style === 'object', 'The `style` prop expects a mapping from style properties to values, ' + @@ -7661,6 +7611,15 @@ function assertValidProps(props) { } function putListener(id, registrationName, listener, transaction) { + if ("production" !== "development") { + // IE8 has no API for event capturing and the `onScroll` event doesn't + // bubble. + if (registrationName === 'onScroll' && + !isEventSupported('scroll', true)) { + monitorCodeUse('react_no_scroll_event'); + console.warn('This browser doesn\'t support the `onScroll` event'); + } + } var container = ReactMount.findReactContainerForID(id); if (container) { var doc = container.nodeType === ELEMENT_NODE_TYPE ? @@ -7675,18 +7634,66 @@ function putListener(id, registrationName, listener, transaction) { ); } +// For HTML, certain tags should omit their close tag. We keep a whitelist for +// those special cased tags. + +var omittedCloseTags = { + 'area': true, + 'base': true, + 'br': true, + 'col': true, + 'embed': true, + 'hr': true, + 'img': true, + 'input': true, + 'keygen': true, + 'link': true, + 'meta': true, + 'param': true, + 'source': true, + 'track': true, + 'wbr': true + // NOTE: menuitem's close tag should be omitted, but that causes problems. +}; + +// We accept any tag to be rendered but since this gets injected into abitrary +// HTML, we want to make sure that it's a safe tag. +// http://www.w3.org/TR/REC-xml/#NT-Name + +var VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset +var validatedTagCache = {}; +var hasOwnProperty = {}.hasOwnProperty; + +function validateDangerousTag(tag) { + if (!hasOwnProperty.call(validatedTagCache, tag)) { + ("production" !== "development" ? invariant(VALID_TAG_REGEX.test(tag), 'Invalid tag: %s', tag) : invariant(VALID_TAG_REGEX.test(tag))); + validatedTagCache[tag] = true; + } +} /** + * Creates a new React class that is idempotent and capable of containing other + * React components. It accepts event listeners and DOM properties that are + * valid according to `DOMProperty`. + * + * - Event listeners: `onClick`, `onMouseDown`, etc. + * - DOM properties: `className`, `name`, `title`, etc. + * + * The `style` property functions differently from the DOM API. It accepts an + * object mapping of style properties to values. + * * @constructor ReactDOMComponent * @extends ReactComponent * @extends ReactMultiChild */ -function ReactDOMComponent(tag, omitClose) { - this._tagOpen = '<' + tag; - this._tagClose = omitClose ? '' : '</' + tag + '>'; +function ReactDOMComponent(tag) { + validateDangerousTag(tag); + this._tag = tag; this.tagName = tag.toUpperCase(); } +ReactDOMComponent.displayName = 'ReactDOMComponent'; + ReactDOMComponent.Mixin = { /** @@ -7710,10 +7717,11 @@ ReactDOMComponent.Mixin = { mountDepth ); assertValidProps(this.props); + var closeTag = omittedCloseTags[this._tag] ? '' : '</' + this._tag + '>'; return ( this._createOpenTagMarkupAndPutListeners(transaction) + this._createContentMarkup(transaction) + - this._tagClose + closeTag ); } ), @@ -7732,7 +7740,7 @@ ReactDOMComponent.Mixin = { */ _createOpenTagMarkupAndPutListeners: function(transaction) { var props = this.props; - var ret = this._tagOpen; + var ret = '<' + this._tag; for (var propKey in props) { if (!props.hasOwnProperty(propKey)) { @@ -7747,7 +7755,7 @@ ReactDOMComponent.Mixin = { } else { if (propKey === STYLE) { if (propValue) { - propValue = props.style = merge(props.style); + propValue = props.style = assign({}, props.style); } propValue = CSSPropertyOperations.createMarkupForStyles(propValue); } @@ -7800,22 +7808,22 @@ ReactDOMComponent.Mixin = { return ''; }, - receiveComponent: function(nextDescriptor, transaction) { - if (nextDescriptor === this._descriptor && - nextDescriptor._owner != null) { - // Since descriptors are immutable after the owner is rendered, + receiveComponent: function(nextElement, transaction) { + if (nextElement === this._currentElement && + nextElement._owner != null) { + // Since elements are immutable after the owner is rendered, // we can do a cheap identity compare here to determine if this is a // superfluous reconcile. It's possible for state to be mutable but such // change should trigger an update of the owner which would recreate - // the descriptor. We explicitly check for the existence of an owner since - // it's possible for a descriptor created outside a composite to be + // the element. We explicitly check for the existence of an owner since + // it's possible for a element created outside a composite to be // deeply mutated and reused. return; } ReactComponent.Mixin.receiveComponent.call( this, - nextDescriptor, + nextElement, transaction ); }, @@ -7825,22 +7833,22 @@ ReactDOMComponent.Mixin = { * attached to the DOM. Reconciles the root DOM node, then recurses. * * @param {ReactReconcileTransaction} transaction - * @param {ReactDescriptor} prevDescriptor + * @param {ReactElement} prevElement * @internal * @overridable */ updateComponent: ReactPerf.measure( 'ReactDOMComponent', 'updateComponent', - function(transaction, prevDescriptor) { - assertValidProps(this._descriptor.props); + function(transaction, prevElement) { + assertValidProps(this._currentElement.props); ReactComponent.Mixin.updateComponent.call( this, transaction, - prevDescriptor + prevElement ); - this._updateDOMProperties(prevDescriptor.props, transaction); - this._updateDOMChildren(prevDescriptor.props, transaction); + this._updateDOMProperties(prevElement.props, transaction); + this._updateDOMChildren(prevElement.props, transaction); } ), @@ -7896,7 +7904,7 @@ ReactDOMComponent.Mixin = { } if (propKey === STYLE) { if (nextProp) { - nextProp = nextProps.style = merge(nextProp); + nextProp = nextProps.style = assign({}, nextProp); } if (lastProp) { // Unset styles on `lastProp` but not on `nextProp`. @@ -8005,28 +8013,24 @@ ReactDOMComponent.Mixin = { }; -mixInto(ReactDOMComponent, ReactComponent.Mixin); -mixInto(ReactDOMComponent, ReactDOMComponent.Mixin); -mixInto(ReactDOMComponent, ReactMultiChild.Mixin); -mixInto(ReactDOMComponent, ReactBrowserComponentMixin); +assign( + ReactDOMComponent.prototype, + ReactComponent.Mixin, + ReactDOMComponent.Mixin, + ReactMultiChild.Mixin, + ReactBrowserComponentMixin +); module.exports = ReactDOMComponent; -},{"./CSSPropertyOperations":5,"./DOMProperty":11,"./DOMPropertyOperations":12,"./ReactBrowserComponentMixin":30,"./ReactBrowserEventEmitter":31,"./ReactComponent":35,"./ReactMount":67,"./ReactMultiChild":68,"./ReactPerf":71,"./escapeTextForBrowser":118,"./invariant":134,"./keyOf":141,"./merge":144,"./mixInto":147}],44:[function(_dereq_,module,exports){ +},{"./CSSPropertyOperations":6,"./DOMProperty":12,"./DOMPropertyOperations":13,"./Object.assign":29,"./ReactBrowserComponentMixin":32,"./ReactBrowserEventEmitter":33,"./ReactComponent":37,"./ReactMount":70,"./ReactMultiChild":71,"./ReactPerf":75,"./escapeTextForBrowser":123,"./invariant":140,"./isEventSupported":141,"./keyOf":147,"./monitorCodeUse":150}],46:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDOMForm */ @@ -8037,10 +8041,11 @@ var EventConstants = _dereq_("./EventConstants"); var LocalEventTrapMixin = _dereq_("./LocalEventTrapMixin"); var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); +var ReactElement = _dereq_("./ReactElement"); var ReactDOM = _dereq_("./ReactDOM"); -// Store a reference to the <form> `ReactDOMComponent`. -var form = ReactDOM.form; +// Store a reference to the <form> `ReactDOMComponent`. TODO: use string +var form = ReactElement.createFactory(ReactDOM.form.type); /** * Since onSubmit doesn't bubble OR capture on the top level in IE8, we need @@ -8057,7 +8062,7 @@ var ReactDOMForm = ReactCompositeComponent.createClass({ // TODO: Instead of using `ReactDOM` directly, we should use JSX. However, // `jshint` fails to parse JSX so in order for linting to work in the open // source repo, we need to just use `ReactDOM.form`. - return this.transferPropsTo(form(null, this.props.children)); + return form(this.props); }, componentDidMount: function() { @@ -8068,21 +8073,14 @@ var ReactDOMForm = ReactCompositeComponent.createClass({ module.exports = ReactDOMForm; -},{"./EventConstants":16,"./LocalEventTrapMixin":26,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41}],45:[function(_dereq_,module,exports){ +},{"./EventConstants":17,"./LocalEventTrapMixin":27,"./ReactBrowserComponentMixin":32,"./ReactCompositeComponent":40,"./ReactDOM":43,"./ReactElement":58}],47:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDOMIDOperations * @typechecks static-only @@ -8259,21 +8257,14 @@ var ReactDOMIDOperations = { module.exports = ReactDOMIDOperations; -},{"./CSSPropertyOperations":5,"./DOMChildrenOperations":10,"./DOMPropertyOperations":12,"./ReactMount":67,"./ReactPerf":71,"./invariant":134,"./setInnerHTML":152}],46:[function(_dereq_,module,exports){ +},{"./CSSPropertyOperations":6,"./DOMChildrenOperations":11,"./DOMPropertyOperations":13,"./ReactMount":70,"./ReactPerf":75,"./invariant":140,"./setInnerHTML":154}],48:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDOMImg */ @@ -8284,10 +8275,11 @@ var EventConstants = _dereq_("./EventConstants"); var LocalEventTrapMixin = _dereq_("./LocalEventTrapMixin"); var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); +var ReactElement = _dereq_("./ReactElement"); var ReactDOM = _dereq_("./ReactDOM"); -// Store a reference to the <img> `ReactDOMComponent`. -var img = ReactDOM.img; +// Store a reference to the <img> `ReactDOMComponent`. TODO: use string +var img = ReactElement.createFactory(ReactDOM.img.type); /** * Since onLoad doesn't bubble OR capture on the top level in IE8, we need to @@ -8313,21 +8305,14 @@ var ReactDOMImg = ReactCompositeComponent.createClass({ module.exports = ReactDOMImg; -},{"./EventConstants":16,"./LocalEventTrapMixin":26,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41}],47:[function(_dereq_,module,exports){ +},{"./EventConstants":17,"./LocalEventTrapMixin":27,"./ReactBrowserComponentMixin":32,"./ReactCompositeComponent":40,"./ReactDOM":43,"./ReactElement":58}],49:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDOMInput */ @@ -8339,17 +8324,26 @@ var DOMPropertyOperations = _dereq_("./DOMPropertyOperations"); var LinkedValueUtils = _dereq_("./LinkedValueUtils"); var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); +var ReactElement = _dereq_("./ReactElement"); var ReactDOM = _dereq_("./ReactDOM"); var ReactMount = _dereq_("./ReactMount"); +var ReactUpdates = _dereq_("./ReactUpdates"); +var assign = _dereq_("./Object.assign"); var invariant = _dereq_("./invariant"); -var merge = _dereq_("./merge"); -// Store a reference to the <input> `ReactDOMComponent`. -var input = ReactDOM.input; +// Store a reference to the <input> `ReactDOMComponent`. TODO: use string +var input = ReactElement.createFactory(ReactDOM.input.type); var instancesByReactID = {}; +function forceUpdateIfMounted() { + /*jshint validthis:true */ + if (this.isMounted()) { + this.forceUpdate(); + } +} + /** * Implements an <input> native component that allows setting these optional * props: `checked`, `value`, `defaultChecked`, and `defaultValue`. @@ -8374,28 +8368,23 @@ var ReactDOMInput = ReactCompositeComponent.createClass({ getInitialState: function() { var defaultValue = this.props.defaultValue; return { - checked: this.props.defaultChecked || false, - value: defaultValue != null ? defaultValue : null + initialChecked: this.props.defaultChecked || false, + initialValue: defaultValue != null ? defaultValue : null }; }, - shouldComponentUpdate: function() { - // Defer any updates to this component during the `onChange` handler. - return !this._isChanging; - }, - render: function() { // Clone `this.props` so we don't mutate the input. - var props = merge(this.props); + var props = assign({}, this.props); props.defaultChecked = null; props.defaultValue = null; var value = LinkedValueUtils.getValue(this); - props.value = value != null ? value : this.state.value; + props.value = value != null ? value : this.state.initialValue; var checked = LinkedValueUtils.getChecked(this); - props.checked = checked != null ? checked : this.state.checked; + props.checked = checked != null ? checked : this.state.initialChecked; props.onChange = this._handleChange; @@ -8435,14 +8424,12 @@ var ReactDOMInput = ReactCompositeComponent.createClass({ var returnValue; var onChange = LinkedValueUtils.getOnChange(this); if (onChange) { - this._isChanging = true; returnValue = onChange.call(this, event); - this._isChanging = false; } - this.setState({ - checked: event.target.checked, - value: event.target.value - }); + // Here we use asap to wait until all updates have propagated, which + // is important when using controlled components within layers: + // https://github.com/facebook/react/issues/1698 + ReactUpdates.asap(forceUpdateIfMounted, this); var name = this.props.name; if (this.props.type === 'radio' && name != null) { @@ -8480,13 +8467,10 @@ var ReactDOMInput = ReactCompositeComponent.createClass({ 'ReactDOMInput: Unknown radio button ID %s.', otherID ) : invariant(otherInstance)); - // In some cases, this will actually change the `checked` state value. - // In other cases, there's no change but this forces a reconcile upon - // which componentDidUpdate will reset the DOM property to whatever it - // should be. - otherInstance.setState({ - checked: false - }); + // If this is a controlled radio button group, forcing the input that + // was previously checked to update will cause it to be come re-checked + // as appropriate. + ReactUpdates.asap(forceUpdateIfMounted, otherInstance); } } @@ -8497,21 +8481,14 @@ var ReactDOMInput = ReactCompositeComponent.createClass({ module.exports = ReactDOMInput; -},{"./AutoFocusMixin":1,"./DOMPropertyOperations":12,"./LinkedValueUtils":25,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./ReactMount":67,"./invariant":134,"./merge":144}],48:[function(_dereq_,module,exports){ +},{"./AutoFocusMixin":2,"./DOMPropertyOperations":13,"./LinkedValueUtils":26,"./Object.assign":29,"./ReactBrowserComponentMixin":32,"./ReactCompositeComponent":40,"./ReactDOM":43,"./ReactElement":58,"./ReactMount":70,"./ReactUpdates":91,"./invariant":140}],50:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDOMOption */ @@ -8520,12 +8497,13 @@ module.exports = ReactDOMInput; var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); +var ReactElement = _dereq_("./ReactElement"); var ReactDOM = _dereq_("./ReactDOM"); var warning = _dereq_("./warning"); -// Store a reference to the <option> `ReactDOMComponent`. -var option = ReactDOM.option; +// Store a reference to the <option> `ReactDOMComponent`. TODO: use string +var option = ReactElement.createFactory(ReactDOM.option.type); /** * Implements an <option> native component that warns when `selected` is set. @@ -8554,21 +8532,14 @@ var ReactDOMOption = ReactCompositeComponent.createClass({ module.exports = ReactDOMOption; -},{"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./warning":158}],49:[function(_dereq_,module,exports){ +},{"./ReactBrowserComponentMixin":32,"./ReactCompositeComponent":40,"./ReactDOM":43,"./ReactElement":58,"./warning":160}],51:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDOMSelect */ @@ -8579,12 +8550,22 @@ var AutoFocusMixin = _dereq_("./AutoFocusMixin"); var LinkedValueUtils = _dereq_("./LinkedValueUtils"); var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); +var ReactElement = _dereq_("./ReactElement"); var ReactDOM = _dereq_("./ReactDOM"); +var ReactUpdates = _dereq_("./ReactUpdates"); -var merge = _dereq_("./merge"); +var assign = _dereq_("./Object.assign"); -// Store a reference to the <select> `ReactDOMComponent`. -var select = ReactDOM.select; +// Store a reference to the <select> `ReactDOMComponent`. TODO: use string +var select = ReactElement.createFactory(ReactDOM.select.type); + +function updateWithPendingValueIfMounted() { + /*jshint validthis:true */ + if (this.isMounted()) { + this.setState({value: this._pendingValue}); + this._pendingValue = 0; + } +} /** * Validation function for `value` and `defaultValue`. @@ -8671,6 +8652,10 @@ var ReactDOMSelect = ReactCompositeComponent.createClass({ return {value: this.props.defaultValue || (this.props.multiple ? [] : '')}; }, + componentWillMount: function() { + this._pendingValue = null; + }, + componentWillReceiveProps: function(nextProps) { if (!this.props.multiple && nextProps.multiple) { this.setState({value: [this.state.value]}); @@ -8679,14 +8664,9 @@ var ReactDOMSelect = ReactCompositeComponent.createClass({ } }, - shouldComponentUpdate: function() { - // Defer any updates to this component during the `onChange` handler. - return !this._isChanging; - }, - render: function() { // Clone `this.props` so we don't mutate the input. - var props = merge(this.props); + var props = assign({}, this.props); props.onChange = this._handleChange; props.value = null; @@ -8711,9 +8691,7 @@ var ReactDOMSelect = ReactCompositeComponent.createClass({ var returnValue; var onChange = LinkedValueUtils.getOnChange(this); if (onChange) { - this._isChanging = true; returnValue = onChange.call(this, event); - this._isChanging = false; } var selectedValue; @@ -8729,7 +8707,8 @@ var ReactDOMSelect = ReactCompositeComponent.createClass({ selectedValue = event.target.value; } - this.setState({value: selectedValue}); + this._pendingValue = selectedValue; + ReactUpdates.asap(updateWithPendingValueIfMounted, this); return returnValue; } @@ -8737,21 +8716,14 @@ var ReactDOMSelect = ReactCompositeComponent.createClass({ module.exports = ReactDOMSelect; -},{"./AutoFocusMixin":1,"./LinkedValueUtils":25,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./merge":144}],50:[function(_dereq_,module,exports){ +},{"./AutoFocusMixin":2,"./LinkedValueUtils":26,"./Object.assign":29,"./ReactBrowserComponentMixin":32,"./ReactCompositeComponent":40,"./ReactDOM":43,"./ReactElement":58,"./ReactUpdates":91}],52:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDOMSelection */ @@ -8810,9 +8782,9 @@ function getIEOffsets(node) { * @return {?object} */ function getModernOffsets(node) { - var selection = window.getSelection(); + var selection = window.getSelection && window.getSelection(); - if (selection.rangeCount === 0) { + if (!selection || selection.rangeCount === 0) { return null; } @@ -8854,7 +8826,6 @@ function getModernOffsets(node) { detectionRange.setStart(anchorNode, anchorOffset); detectionRange.setEnd(focusNode, focusOffset); var isBackward = detectionRange.collapsed; - detectionRange.detach(); return { start: isBackward ? end : start, @@ -8901,8 +8872,11 @@ function setIEOffsets(node, offsets) { * @param {object} offsets */ function setModernOffsets(node, offsets) { - var selection = window.getSelection(); + if (!window.getSelection) { + return; + } + var selection = window.getSelection(); var length = node[getTextContentAccessor()].length; var start = Math.min(offsets.start, length); var end = typeof offsets.end === 'undefined' ? @@ -8931,8 +8905,6 @@ function setModernOffsets(node, offsets) { range.setEnd(endMarker.node, endMarker.offset); selection.addRange(range); } - - range.detach(); } } @@ -8953,21 +8925,14 @@ var ReactDOMSelection = { module.exports = ReactDOMSelection; -},{"./ExecutionEnvironment":22,"./getNodeForCharacterOffset":127,"./getTextContentAccessor":129}],51:[function(_dereq_,module,exports){ +},{"./ExecutionEnvironment":23,"./getNodeForCharacterOffset":133,"./getTextContentAccessor":135}],53:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDOMTextarea */ @@ -8979,15 +8944,24 @@ var DOMPropertyOperations = _dereq_("./DOMPropertyOperations"); var LinkedValueUtils = _dereq_("./LinkedValueUtils"); var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); +var ReactElement = _dereq_("./ReactElement"); var ReactDOM = _dereq_("./ReactDOM"); +var ReactUpdates = _dereq_("./ReactUpdates"); +var assign = _dereq_("./Object.assign"); var invariant = _dereq_("./invariant"); -var merge = _dereq_("./merge"); var warning = _dereq_("./warning"); -// Store a reference to the <textarea> `ReactDOMComponent`. -var textarea = ReactDOM.textarea; +// Store a reference to the <textarea> `ReactDOMComponent`. TODO: use string +var textarea = ReactElement.createFactory(ReactDOM.textarea.type); + +function forceUpdateIfMounted() { + /*jshint validthis:true */ + if (this.isMounted()) { + this.forceUpdate(); + } +} /** * Implements a <textarea> native component that allows setting `value`, and @@ -9048,14 +9022,9 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({ }; }, - shouldComponentUpdate: function() { - // Defer any updates to this component during the `onChange` handler. - return !this._isChanging; - }, - render: function() { // Clone `this.props` so we don't mutate the input. - var props = merge(this.props); + var props = assign({}, this.props); ("production" !== "development" ? invariant( props.dangerouslySetInnerHTML == null, @@ -9085,11 +9054,9 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({ var returnValue; var onChange = LinkedValueUtils.getOnChange(this); if (onChange) { - this._isChanging = true; returnValue = onChange.call(this, event); - this._isChanging = false; } - this.setState({value: event.target.value}); + ReactUpdates.asap(forceUpdateIfMounted, this); return returnValue; } @@ -9097,21 +9064,14 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({ module.exports = ReactDOMTextarea; -},{"./AutoFocusMixin":1,"./DOMPropertyOperations":12,"./LinkedValueUtils":25,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./invariant":134,"./merge":144,"./warning":158}],52:[function(_dereq_,module,exports){ +},{"./AutoFocusMixin":2,"./DOMPropertyOperations":13,"./LinkedValueUtils":26,"./Object.assign":29,"./ReactBrowserComponentMixin":32,"./ReactCompositeComponent":40,"./ReactDOM":43,"./ReactElement":58,"./ReactUpdates":91,"./invariant":140,"./warning":160}],54:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDefaultBatchingStrategy */ @@ -9121,8 +9081,8 @@ module.exports = ReactDOMTextarea; var ReactUpdates = _dereq_("./ReactUpdates"); var Transaction = _dereq_("./Transaction"); +var assign = _dereq_("./Object.assign"); var emptyFunction = _dereq_("./emptyFunction"); -var mixInto = _dereq_("./mixInto"); var RESET_BATCHED_UPDATES = { initialize: emptyFunction, @@ -9142,12 +9102,15 @@ function ReactDefaultBatchingStrategyTransaction() { this.reinitializeTransaction(); } -mixInto(ReactDefaultBatchingStrategyTransaction, Transaction.Mixin); -mixInto(ReactDefaultBatchingStrategyTransaction, { - getTransactionWrappers: function() { - return TRANSACTION_WRAPPERS; +assign( + ReactDefaultBatchingStrategyTransaction.prototype, + Transaction.Mixin, + { + getTransactionWrappers: function() { + return TRANSACTION_WRAPPERS; + } } -}); +); var transaction = new ReactDefaultBatchingStrategyTransaction(); @@ -9174,21 +9137,14 @@ var ReactDefaultBatchingStrategy = { module.exports = ReactDefaultBatchingStrategy; -},{"./ReactUpdates":87,"./Transaction":104,"./emptyFunction":116,"./mixInto":147}],53:[function(_dereq_,module,exports){ +},{"./Object.assign":29,"./ReactUpdates":91,"./Transaction":107,"./emptyFunction":121}],55:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDefaultInjection */ @@ -9208,7 +9164,7 @@ var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); var ReactComponentBrowserEnvironment = _dereq_("./ReactComponentBrowserEnvironment"); var ReactDefaultBatchingStrategy = _dereq_("./ReactDefaultBatchingStrategy"); -var ReactDOM = _dereq_("./ReactDOM"); +var ReactDOMComponent = _dereq_("./ReactDOMComponent"); var ReactDOMButton = _dereq_("./ReactDOMButton"); var ReactDOMForm = _dereq_("./ReactDOMForm"); var ReactDOMImg = _dereq_("./ReactDOMImg"); @@ -9253,18 +9209,22 @@ function inject() { BeforeInputEventPlugin: BeforeInputEventPlugin }); - ReactInjection.DOM.injectComponentClasses({ - button: ReactDOMButton, - form: ReactDOMForm, - img: ReactDOMImg, - input: ReactDOMInput, - option: ReactDOMOption, - select: ReactDOMSelect, - textarea: ReactDOMTextarea, - - html: createFullPageComponent(ReactDOM.html), - head: createFullPageComponent(ReactDOM.head), - body: createFullPageComponent(ReactDOM.body) + ReactInjection.NativeComponent.injectGenericComponentClass( + ReactDOMComponent + ); + + ReactInjection.NativeComponent.injectComponentClasses({ + 'button': ReactDOMButton, + 'form': ReactDOMForm, + 'img': ReactDOMImg, + 'input': ReactDOMInput, + 'option': ReactDOMOption, + 'select': ReactDOMSelect, + 'textarea': ReactDOMTextarea, + + 'html': createFullPageComponent('html'), + 'head': createFullPageComponent('head'), + 'body': createFullPageComponent('body') }); // This needs to happen after createFullPageComponent() otherwise the mixin @@ -9274,7 +9234,7 @@ function inject() { ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig); ReactInjection.DOMProperty.injectDOMPropertyConfig(SVGDOMPropertyConfig); - ReactInjection.EmptyComponent.injectEmptyComponent(ReactDOM.noscript); + ReactInjection.EmptyComponent.injectEmptyComponent('noscript'); ReactInjection.Updates.injectReconcileTransaction( ReactComponentBrowserEnvironment.ReactReconcileTransaction @@ -9304,21 +9264,14 @@ module.exports = { inject: inject }; -},{"./BeforeInputEventPlugin":2,"./ChangeEventPlugin":7,"./ClientReactRootIndex":8,"./CompositionEventPlugin":9,"./DefaultEventPluginOrder":14,"./EnterLeaveEventPlugin":15,"./ExecutionEnvironment":22,"./HTMLDOMPropertyConfig":23,"./MobileSafariClickEventPlugin":27,"./ReactBrowserComponentMixin":30,"./ReactComponentBrowserEnvironment":36,"./ReactDOM":41,"./ReactDOMButton":42,"./ReactDOMForm":44,"./ReactDOMImg":46,"./ReactDOMInput":47,"./ReactDOMOption":48,"./ReactDOMSelect":49,"./ReactDOMTextarea":51,"./ReactDefaultBatchingStrategy":52,"./ReactDefaultPerf":54,"./ReactEventListener":61,"./ReactInjection":62,"./ReactInstanceHandles":64,"./ReactMount":67,"./SVGDOMPropertyConfig":89,"./SelectEventPlugin":90,"./ServerReactRootIndex":91,"./SimpleEventPlugin":92,"./createFullPageComponent":112}],54:[function(_dereq_,module,exports){ +},{"./BeforeInputEventPlugin":3,"./ChangeEventPlugin":8,"./ClientReactRootIndex":9,"./CompositionEventPlugin":10,"./DefaultEventPluginOrder":15,"./EnterLeaveEventPlugin":16,"./ExecutionEnvironment":23,"./HTMLDOMPropertyConfig":24,"./MobileSafariClickEventPlugin":28,"./ReactBrowserComponentMixin":32,"./ReactComponentBrowserEnvironment":38,"./ReactDOMButton":44,"./ReactDOMComponent":45,"./ReactDOMForm":46,"./ReactDOMImg":48,"./ReactDOMInput":49,"./ReactDOMOption":50,"./ReactDOMSelect":51,"./ReactDOMTextarea":53,"./ReactDefaultBatchingStrategy":54,"./ReactDefaultPerf":56,"./ReactEventListener":63,"./ReactInjection":64,"./ReactInstanceHandles":66,"./ReactMount":70,"./SVGDOMPropertyConfig":92,"./SelectEventPlugin":93,"./ServerReactRootIndex":94,"./SimpleEventPlugin":95,"./createFullPageComponent":116}],56:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDefaultPerf * @typechecks static-only @@ -9397,19 +9350,23 @@ var ReactDefaultPerf = { ); }, - printWasted: function(measurements) { - measurements = measurements || ReactDefaultPerf._allMeasurements; + getMeasurementsSummaryMap: function(measurements) { var summary = ReactDefaultPerfAnalysis.getInclusiveSummary( measurements, true ); - console.table(summary.map(function(item) { + return summary.map(function(item) { return { 'Owner > component': item.componentName, 'Wasted time (ms)': item.time, 'Instances': item.count }; - })); + }); + }, + + printWasted: function(measurements) { + measurements = measurements || ReactDefaultPerf._allMeasurements; + console.table(ReactDefaultPerf.getMeasurementsSummaryMap(measurements)); console.log( 'Total time:', ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms' @@ -9447,7 +9404,7 @@ var ReactDefaultPerf = { }, measure: function(moduleName, fnName, func) { - return function() {var args=Array.prototype.slice.call(arguments,0); + return function() {for (var args=[],$__0=0,$__1=arguments.length;$__0<$__1;$__0++) args.push(arguments[$__0]); var totalTime; var rv; var start; @@ -9567,26 +9524,19 @@ var ReactDefaultPerf = { module.exports = ReactDefaultPerf; -},{"./DOMProperty":11,"./ReactDefaultPerfAnalysis":55,"./ReactMount":67,"./ReactPerf":71,"./performanceNow":151}],55:[function(_dereq_,module,exports){ +},{"./DOMProperty":12,"./ReactDefaultPerfAnalysis":57,"./ReactMount":70,"./ReactPerf":75,"./performanceNow":153}],57:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactDefaultPerfAnalysis */ -var merge = _dereq_("./merge"); +var assign = _dereq_("./Object.assign"); // Don't try to save users less than 1.2ms (a number I made up) var DONT_CARE_THRESHOLD = 1.2; @@ -9641,7 +9591,11 @@ function getExclusiveSummary(measurements) { for (var i = 0; i < measurements.length; i++) { var measurement = measurements[i]; - var allIDs = merge(measurement.exclusive, measurement.inclusive); + var allIDs = assign( + {}, + measurement.exclusive, + measurement.inclusive + ); for (var id in allIDs) { displayName = measurement.displayNames[id].current; @@ -9689,7 +9643,11 @@ function getInclusiveSummary(measurements, onlyClean) { for (var i = 0; i < measurements.length; i++) { var measurement = measurements[i]; - var allIDs = merge(measurement.exclusive, measurement.inclusive); + var allIDs = assign( + {}, + measurement.exclusive, + measurement.inclusive + ); var cleanComponents; if (onlyClean) { @@ -9744,11 +9702,11 @@ function getUnchangedComponents(measurement) { // the amount of time it took to render the entire subtree. var cleanComponents = {}; var dirtyLeafIDs = Object.keys(measurement.writes); - var allIDs = merge(measurement.exclusive, measurement.inclusive); + var allIDs = assign({}, measurement.exclusive, measurement.inclusive); for (var id in allIDs) { var isDirty = false; - // For each component that rendered, see if a component that triggerd + // For each component that rendered, see if a component that triggered // a DOM op is in its subtree. for (var i = 0; i < dirtyLeafIDs.length; i++) { if (dirtyLeafIDs[i].indexOf(id) === 0) { @@ -9772,23 +9730,16 @@ var ReactDefaultPerfAnalysis = { module.exports = ReactDefaultPerfAnalysis; -},{"./merge":144}],56:[function(_dereq_,module,exports){ +},{"./Object.assign":29}],58:[function(_dereq_,module,exports){ /** - * Copyright 2014 Facebook, Inc. + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * - * @providesModule ReactDescriptor + * @providesModule ReactElement */ "use strict"; @@ -9796,9 +9747,13 @@ module.exports = ReactDefaultPerfAnalysis; var ReactContext = _dereq_("./ReactContext"); var ReactCurrentOwner = _dereq_("./ReactCurrentOwner"); -var merge = _dereq_("./merge"); var warning = _dereq_("./warning"); +var RESERVED_PROPS = { + key: true, + ref: true +}; + /** * Warn for mutations. * @@ -9840,7 +9795,7 @@ var useMutationMembrane = false; * Warn for mutations. * * @internal - * @param {object} descriptor + * @param {object} element */ function defineMutationMembrane(prototype) { try { @@ -9857,161 +9812,145 @@ function defineMutationMembrane(prototype) { } /** - * Transfer static properties from the source to the target. Functions are - * rebound to have this reflect the original source. - */ -function proxyStaticMethods(target, source) { - if (typeof source !== 'function') { - return; - } - for (var key in source) { - if (source.hasOwnProperty(key)) { - var value = source[key]; - if (typeof value === 'function') { - var bound = value.bind(source); - // Copy any properties defined on the function, such as `isRequired` on - // a PropTypes validator. (mergeInto refuses to work on functions.) - for (var k in value) { - if (value.hasOwnProperty(k)) { - bound[k] = value[k]; - } - } - target[key] = bound; - } else { - target[key] = value; - } - } - } -} - -/** - * Base constructor for all React descriptors. This is only used to make this + * Base constructor for all React elements. This is only used to make this * work with a dynamic instanceof check. Nothing should live on this prototype. * * @param {*} type + * @param {string|object} ref + * @param {*} key + * @param {*} props * @internal */ -var ReactDescriptor = function() {}; +var ReactElement = function(type, key, ref, owner, context, props) { + // Built-in properties that belong on the element + this.type = type; + this.key = key; + this.ref = ref; -if ("production" !== "development") { - defineMutationMembrane(ReactDescriptor.prototype); -} - -ReactDescriptor.createFactory = function(type) { - - var descriptorPrototype = Object.create(ReactDescriptor.prototype); - - var factory = function(props, children) { - // For consistency we currently allocate a new object for every descriptor. - // This protects the descriptor from being mutated by the original props - // object being mutated. It also protects the original props object from - // being mutated by children arguments and default props. This behavior - // comes with a performance cost and could be deprecated in the future. - // It could also be optimized with a smarter JSX transform. - if (props == null) { - props = {}; - } else if (typeof props === 'object') { - props = merge(props); - } - - // Children can be more than one argument, and those are transferred onto - // the newly allocated props object. - var childrenLength = arguments.length - 1; - if (childrenLength === 1) { - props.children = children; - } else if (childrenLength > 1) { - var childArray = Array(childrenLength); - for (var i = 0; i < childrenLength; i++) { - childArray[i] = arguments[i + 1]; - } - props.children = childArray; + // Record the component responsible for creating this element. + this._owner = owner; + + // TODO: Deprecate withContext, and then the context becomes accessible + // through the owner. + this._context = context; + + if ("production" !== "development") { + // The validation flag and props are currently mutative. We put them on + // an external backing store so that we can freeze the whole object. + // This can be replaced with a WeakMap once they are implemented in + // commonly used development environments. + this._store = { validated: false, props: props }; + + // We're not allowed to set props directly on the object so we early + // return and rely on the prototype membrane to forward to the backing + // store. + if (useMutationMembrane) { + Object.freeze(this); + return; } + } + + this.props = props; +}; + +// We intentionally don't expose the function on the constructor property. +// ReactElement should be indistinguishable from a plain object. +ReactElement.prototype = { + _isReactElement: true +}; - // Initialize the descriptor object - var descriptor = Object.create(descriptorPrototype); +if ("production" !== "development") { + defineMutationMembrane(ReactElement.prototype); +} + +ReactElement.createElement = function(type, config, children) { + var propName; - // Record the component responsible for creating this descriptor. - descriptor._owner = ReactCurrentOwner.current; + // Reserved names are extracted + var props = {}; - // TODO: Deprecate withContext, and then the context becomes accessible - // through the owner. - descriptor._context = ReactContext.current; + var key = null; + var ref = null; + if (config != null) { + ref = config.ref === undefined ? null : config.ref; if ("production" !== "development") { - // The validation flag and props are currently mutative. We put them on - // an external backing store so that we can freeze the whole object. - // This can be replaced with a WeakMap once they are implemented in - // commonly used development environments. - descriptor._store = { validated: false, props: props }; - - // We're not allowed to set props directly on the object so we early - // return and rely on the prototype membrane to forward to the backing - // store. - if (useMutationMembrane) { - Object.freeze(descriptor); - return descriptor; + ("production" !== "development" ? warning( + config.key !== null, + 'createElement(...): Encountered component with a `key` of null. In ' + + 'a future version, this will be treated as equivalent to the string ' + + '\'null\'; instead, provide an explicit key or use undefined.' + ) : null); + } + // TODO: Change this back to `config.key === undefined` + key = config.key == null ? null : '' + config.key; + // Remaining properties are added to a new props object + for (propName in config) { + if (config.hasOwnProperty(propName) && + !RESERVED_PROPS.hasOwnProperty(propName)) { + props[propName] = config[propName]; } } + } - descriptor.props = props; - return descriptor; - }; + // Children can be more than one argument, and those are transferred onto + // the newly allocated props object. + var childrenLength = arguments.length - 2; + if (childrenLength === 1) { + props.children = children; + } else if (childrenLength > 1) { + var childArray = Array(childrenLength); + for (var i = 0; i < childrenLength; i++) { + childArray[i] = arguments[i + 2]; + } + props.children = childArray; + } + + // Resolve default props + if (type.defaultProps) { + var defaultProps = type.defaultProps; + for (propName in defaultProps) { + if (typeof props[propName] === 'undefined') { + props[propName] = defaultProps[propName]; + } + } + } - // Currently we expose the prototype of the descriptor so that - // <Foo /> instanceof Foo works. This is controversial pattern. - factory.prototype = descriptorPrototype; + return new ReactElement( + type, + key, + ref, + ReactCurrentOwner.current, + ReactContext.current, + props + ); +}; +ReactElement.createFactory = function(type) { + var factory = ReactElement.createElement.bind(null, type); // Expose the type on the factory and the prototype so that it can be - // easily accessed on descriptors. E.g. <Foo />.type === Foo.type and for - // static methods like <Foo />.type.staticMethod(); - // This should not be named constructor since this may not be the function - // that created the descriptor, and it may not even be a constructor. + // easily accessed on elements. E.g. <Foo />.type === Foo.type. + // This should not be named `constructor` since this may not be the function + // that created the element, and it may not even be a constructor. factory.type = type; - descriptorPrototype.type = type; - - proxyStaticMethods(factory, type); - - // Expose a unique constructor on the prototype is that this works with type - // systems that compare constructor properties: <Foo />.constructor === Foo - // This may be controversial since it requires a known factory function. - descriptorPrototype.constructor = factory; - return factory; - }; -ReactDescriptor.cloneAndReplaceProps = function(oldDescriptor, newProps) { - var newDescriptor = Object.create(oldDescriptor.constructor.prototype); - // It's important that this property order matches the hidden class of the - // original descriptor to maintain perf. - newDescriptor._owner = oldDescriptor._owner; - newDescriptor._context = oldDescriptor._context; +ReactElement.cloneAndReplaceProps = function(oldElement, newProps) { + var newElement = new ReactElement( + oldElement.type, + oldElement.key, + oldElement.ref, + oldElement._owner, + oldElement._context, + newProps + ); if ("production" !== "development") { - newDescriptor._store = { - validated: oldDescriptor._store.validated, - props: newProps - }; - if (useMutationMembrane) { - Object.freeze(newDescriptor); - return newDescriptor; - } + // If the key on the original is valid, then the clone is valid + newElement._store.validated = oldElement._store.validated; } - - newDescriptor.props = newProps; - return newDescriptor; -}; - -/** - * Checks if a value is a valid descriptor constructor. - * - * @param {*} - * @return {boolean} - * @public - */ -ReactDescriptor.isValidFactory = function(factory) { - return typeof factory === 'function' && - factory.prototype instanceof ReactDescriptor; + return newElement; }; /** @@ -10019,41 +9958,44 @@ ReactDescriptor.isValidFactory = function(factory) { * @return {boolean} True if `object` is a valid component. * @final */ -ReactDescriptor.isValidDescriptor = function(object) { - return object instanceof ReactDescriptor; +ReactElement.isValidElement = function(object) { + // ReactTestUtils is often used outside of beforeEach where as React is + // within it. This leads to two different instances of React on the same + // page. To identify a element from a different React instance we use + // a flag instead of an instanceof check. + var isElement = !!(object && object._isReactElement); + // if (isElement && !(object instanceof ReactElement)) { + // This is an indicator that you're using multiple versions of React at the + // same time. This will screw with ownership and stuff. Fix it, please. + // TODO: We could possibly warn here. + // } + return isElement; }; -module.exports = ReactDescriptor; +module.exports = ReactElement; -},{"./ReactContext":39,"./ReactCurrentOwner":40,"./merge":144,"./warning":158}],57:[function(_dereq_,module,exports){ +},{"./ReactContext":41,"./ReactCurrentOwner":42,"./warning":160}],59:[function(_dereq_,module,exports){ /** - * Copyright 2014 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 + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * - * @providesModule ReactDescriptorValidator + * @providesModule ReactElementValidator */ /** - * ReactDescriptorValidator provides a wrapper around a descriptor factory - * which validates the props passed to the descriptor. This is intended to be + * ReactElementValidator provides a wrapper around a element factory + * which validates the props passed to the element. This is intended to be * used only in DEV and could be replaced by a static type checker for languages * that support it. */ "use strict"; -var ReactDescriptor = _dereq_("./ReactDescriptor"); +var ReactElement = _dereq_("./ReactElement"); var ReactPropTypeLocations = _dereq_("./ReactPropTypeLocations"); var ReactCurrentOwner = _dereq_("./ReactCurrentOwner"); @@ -10096,7 +10038,7 @@ function getCurrentOwnerDisplayName() { * @param {*} parentType component's parent's type. */ function validateExplicitKey(component, parentType) { - if (component._store.validated || component.props.key != null) { + if (component._store.validated || component.key != null) { return; } component._store.validated = true; @@ -10202,11 +10144,11 @@ function validateChildKeys(component, parentType) { if (Array.isArray(component)) { for (var i = 0; i < component.length; i++) { var child = component[i]; - if (ReactDescriptor.isValidDescriptor(child)) { + if (ReactElement.isValidElement(child)) { validateExplicitKey(child, parentType); } } - } else if (ReactDescriptor.isValidDescriptor(component)) { + } else if (ReactElement.isValidElement(component)) { // This component was passed in a valid location. component._store.validated = true; } else if (component && typeof component === 'object') { @@ -10252,85 +10194,70 @@ function checkPropTypes(componentName, propTypes, props, location) { } } -var ReactDescriptorValidator = { +var ReactElementValidator = { - /** - * Wraps a descriptor factory function in another function which validates - * the props and context of the descriptor and warns about any failed type - * checks. - * - * @param {function} factory The original descriptor factory - * @param {object?} propTypes A prop type definition set - * @param {object?} contextTypes A context type definition set - * @return {object} The component descriptor, which may be invalid. - * @private - */ - createFactory: function(factory, propTypes, contextTypes) { - var validatedFactory = function(props, children) { - var descriptor = factory.apply(this, arguments); + createElement: function(type, props, children) { + var element = ReactElement.createElement.apply(this, arguments); - for (var i = 1; i < arguments.length; i++) { - validateChildKeys(arguments[i], descriptor.type); - } - - var name = descriptor.type.displayName; - if (propTypes) { - checkPropTypes( - name, - propTypes, - descriptor.props, - ReactPropTypeLocations.prop - ); - } - if (contextTypes) { - checkPropTypes( - name, - contextTypes, - descriptor._context, - ReactPropTypeLocations.context - ); - } - return descriptor; - }; + // The result can be nullish if a mock or a custom function is used. + // TODO: Drop this when these are no longer allowed as the type argument. + if (element == null) { + return element; + } - validatedFactory.prototype = factory.prototype; - validatedFactory.type = factory.type; + for (var i = 2; i < arguments.length; i++) { + validateChildKeys(arguments[i], type); + } - // Copy static properties - for (var key in factory) { - if (factory.hasOwnProperty(key)) { - validatedFactory[key] = factory[key]; - } + var name = type.displayName; + if (type.propTypes) { + checkPropTypes( + name, + type.propTypes, + element.props, + ReactPropTypeLocations.prop + ); } + if (type.contextTypes) { + checkPropTypes( + name, + type.contextTypes, + element._context, + ReactPropTypeLocations.context + ); + } + return element; + }, + createFactory: function(type) { + var validatedFactory = ReactElementValidator.createElement.bind( + null, + type + ); + validatedFactory.type = type; return validatedFactory; } }; -module.exports = ReactDescriptorValidator; +module.exports = ReactElementValidator; -},{"./ReactCurrentOwner":40,"./ReactDescriptor":56,"./ReactPropTypeLocations":74,"./monitorCodeUse":148}],58:[function(_dereq_,module,exports){ +},{"./ReactCurrentOwner":42,"./ReactElement":58,"./ReactPropTypeLocations":78,"./monitorCodeUse":150}],60:[function(_dereq_,module,exports){ /** - * Copyright 2014 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 + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactEmptyComponent */ "use strict"; +var ReactElement = _dereq_("./ReactElement"); + var invariant = _dereq_("./invariant"); var component; @@ -10340,7 +10267,7 @@ var nullComponentIdsRegistry = {}; var ReactEmptyComponentInjection = { injectEmptyComponent: function(emptyComponent) { - component = emptyComponent; + component = ReactElement.createFactory(emptyComponent); } }; @@ -10390,21 +10317,14 @@ var ReactEmptyComponent = { module.exports = ReactEmptyComponent; -},{"./invariant":134}],59:[function(_dereq_,module,exports){ +},{"./ReactElement":58,"./invariant":140}],61:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactErrorUtils * @typechecks @@ -10429,21 +10349,14 @@ var ReactErrorUtils = { module.exports = ReactErrorUtils; -},{}],60:[function(_dereq_,module,exports){ +},{}],62:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactEventEmitterMixin */ @@ -10486,21 +10399,14 @@ var ReactEventEmitterMixin = { module.exports = ReactEventEmitterMixin; -},{"./EventPluginHub":18}],61:[function(_dereq_,module,exports){ +},{"./EventPluginHub":19}],63:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactEventListener * @typechecks static-only @@ -10515,9 +10421,9 @@ var ReactInstanceHandles = _dereq_("./ReactInstanceHandles"); var ReactMount = _dereq_("./ReactMount"); var ReactUpdates = _dereq_("./ReactUpdates"); +var assign = _dereq_("./Object.assign"); var getEventTarget = _dereq_("./getEventTarget"); var getUnboundedScrollPosition = _dereq_("./getUnboundedScrollPosition"); -var mixInto = _dereq_("./mixInto"); /** * Finds the parent React component of `node`. @@ -10543,7 +10449,7 @@ function TopLevelCallbackBookKeeping(topLevelType, nativeEvent) { this.nativeEvent = nativeEvent; this.ancestors = []; } -mixInto(TopLevelCallbackBookKeeping, { +assign(TopLevelCallbackBookKeeping.prototype, { destructor: function() { this.topLevelType = null; this.nativeEvent = null; @@ -10677,21 +10583,14 @@ var ReactEventListener = { module.exports = ReactEventListener; -},{"./EventListener":17,"./ExecutionEnvironment":22,"./PooledClass":28,"./ReactInstanceHandles":64,"./ReactMount":67,"./ReactUpdates":87,"./getEventTarget":125,"./getUnboundedScrollPosition":130,"./mixInto":147}],62:[function(_dereq_,module,exports){ +},{"./EventListener":18,"./ExecutionEnvironment":23,"./Object.assign":29,"./PooledClass":30,"./ReactInstanceHandles":66,"./ReactMount":70,"./ReactUpdates":91,"./getEventTarget":131,"./getUnboundedScrollPosition":136}],64:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactInjection */ @@ -10702,9 +10601,9 @@ var DOMProperty = _dereq_("./DOMProperty"); var EventPluginHub = _dereq_("./EventPluginHub"); var ReactComponent = _dereq_("./ReactComponent"); var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); -var ReactDOM = _dereq_("./ReactDOM"); var ReactEmptyComponent = _dereq_("./ReactEmptyComponent"); var ReactBrowserEventEmitter = _dereq_("./ReactBrowserEventEmitter"); +var ReactNativeComponent = _dereq_("./ReactNativeComponent"); var ReactPerf = _dereq_("./ReactPerf"); var ReactRootIndex = _dereq_("./ReactRootIndex"); var ReactUpdates = _dereq_("./ReactUpdates"); @@ -10715,8 +10614,8 @@ var ReactInjection = { DOMProperty: DOMProperty.injection, EmptyComponent: ReactEmptyComponent.injection, EventPluginHub: EventPluginHub.injection, - DOM: ReactDOM.injection, EventEmitter: ReactBrowserEventEmitter.injection, + NativeComponent: ReactNativeComponent.injection, Perf: ReactPerf.injection, RootIndex: ReactRootIndex.injection, Updates: ReactUpdates.injection @@ -10724,21 +10623,14 @@ var ReactInjection = { module.exports = ReactInjection; -},{"./DOMProperty":11,"./EventPluginHub":18,"./ReactBrowserEventEmitter":31,"./ReactComponent":35,"./ReactCompositeComponent":38,"./ReactDOM":41,"./ReactEmptyComponent":58,"./ReactPerf":71,"./ReactRootIndex":78,"./ReactUpdates":87}],63:[function(_dereq_,module,exports){ +},{"./DOMProperty":12,"./EventPluginHub":19,"./ReactBrowserEventEmitter":33,"./ReactComponent":37,"./ReactCompositeComponent":40,"./ReactEmptyComponent":60,"./ReactNativeComponent":73,"./ReactPerf":75,"./ReactRootIndex":82,"./ReactUpdates":91}],65:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactInputSelection */ @@ -10867,21 +10759,14 @@ var ReactInputSelection = { module.exports = ReactInputSelection; -},{"./ReactDOMSelection":50,"./containsNode":109,"./focusNode":120,"./getActiveElement":122}],64:[function(_dereq_,module,exports){ +},{"./ReactDOMSelection":52,"./containsNode":114,"./focusNode":125,"./getActiveElement":127}],66:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactInstanceHandles * @typechecks static-only @@ -11207,21 +11092,259 @@ var ReactInstanceHandles = { module.exports = ReactInstanceHandles; -},{"./ReactRootIndex":78,"./invariant":134}],65:[function(_dereq_,module,exports){ +},{"./ReactRootIndex":82,"./invariant":140}],67:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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 + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * - * http://www.apache.org/licenses/LICENSE-2.0 + * @providesModule ReactLegacyElement + */ + +"use strict"; + +var ReactCurrentOwner = _dereq_("./ReactCurrentOwner"); + +var invariant = _dereq_("./invariant"); +var monitorCodeUse = _dereq_("./monitorCodeUse"); +var warning = _dereq_("./warning"); + +var legacyFactoryLogs = {}; +function warnForLegacyFactoryCall() { + if (!ReactLegacyElementFactory._isLegacyCallWarningEnabled) { + return; + } + var owner = ReactCurrentOwner.current; + var name = owner && owner.constructor ? owner.constructor.displayName : ''; + if (!name) { + name = 'Something'; + } + if (legacyFactoryLogs.hasOwnProperty(name)) { + return; + } + legacyFactoryLogs[name] = true; + ("production" !== "development" ? warning( + false, + name + ' is calling a React component directly. ' + + 'Use a factory or JSX instead. See: http://fb.me/react-legacyfactory' + ) : null); + monitorCodeUse('react_legacy_factory_call', { version: 3, name: name }); +} + +function warnForPlainFunctionType(type) { + var isReactClass = + type.prototype && + typeof type.prototype.mountComponent === 'function' && + typeof type.prototype.receiveComponent === 'function'; + if (isReactClass) { + ("production" !== "development" ? warning( + false, + 'Did not expect to get a React class here. Use `Component` instead ' + + 'of `Component.type` or `this.constructor`.' + ) : null); + } else { + if (!type._reactWarnedForThisType) { + try { + type._reactWarnedForThisType = true; + } catch (x) { + // just incase this is a frozen object or some special object + } + monitorCodeUse( + 'react_non_component_in_jsx', + { version: 3, name: type.name } + ); + } + ("production" !== "development" ? warning( + false, + 'This JSX uses a plain function. Only React components are ' + + 'valid in React\'s JSX transform.' + ) : null); + } +} + +function warnForNonLegacyFactory(type) { + ("production" !== "development" ? warning( + false, + 'Do not pass React.DOM.' + type.type + ' to JSX or createFactory. ' + + 'Use the string "' + type.type + '" instead.' + ) : null); +} + +/** + * Transfer static properties from the source to the target. Functions are + * rebound to have this reflect the original source. + */ +function proxyStaticMethods(target, source) { + if (typeof source !== 'function') { + return; + } + for (var key in source) { + if (source.hasOwnProperty(key)) { + var value = source[key]; + if (typeof value === 'function') { + var bound = value.bind(source); + // Copy any properties defined on the function, such as `isRequired` on + // a PropTypes validator. + for (var k in value) { + if (value.hasOwnProperty(k)) { + bound[k] = value[k]; + } + } + target[key] = bound; + } else { + target[key] = value; + } + } + } +} + +// We use an object instead of a boolean because booleans are ignored by our +// mocking libraries when these factories gets mocked. +var LEGACY_MARKER = {}; +var NON_LEGACY_MARKER = {}; + +var ReactLegacyElementFactory = {}; + +ReactLegacyElementFactory.wrapCreateFactory = function(createFactory) { + var legacyCreateFactory = function(type) { + if (typeof type !== 'function') { + // Non-function types cannot be legacy factories + return createFactory(type); + } + + if (type.isReactNonLegacyFactory) { + // This is probably a factory created by ReactDOM we unwrap it to get to + // the underlying string type. It shouldn't have been passed here so we + // warn. + if ("production" !== "development") { + warnForNonLegacyFactory(type); + } + return createFactory(type.type); + } + + if (type.isReactLegacyFactory) { + // This is probably a legacy factory created by ReactCompositeComponent. + // We unwrap it to get to the underlying class. + return createFactory(type.type); + } + + if ("production" !== "development") { + warnForPlainFunctionType(type); + } + + // Unless it's a legacy factory, then this is probably a plain function, + // that is expecting to be invoked by JSX. We can just return it as is. + return type; + }; + return legacyCreateFactory; +}; + +ReactLegacyElementFactory.wrapCreateElement = function(createElement) { + var legacyCreateElement = function(type, props, children) { + if (typeof type !== 'function') { + // Non-function types cannot be legacy factories + return createElement.apply(this, arguments); + } + + var args; + + if (type.isReactNonLegacyFactory) { + // This is probably a factory created by ReactDOM we unwrap it to get to + // the underlying string type. It shouldn't have been passed here so we + // warn. + if ("production" !== "development") { + warnForNonLegacyFactory(type); + } + args = Array.prototype.slice.call(arguments, 0); + args[0] = type.type; + return createElement.apply(this, args); + } + + if (type.isReactLegacyFactory) { + // This is probably a legacy factory created by ReactCompositeComponent. + // We unwrap it to get to the underlying class. + if (type._isMockFunction) { + // If this is a mock function, people will expect it to be called. We + // will actually call the original mock factory function instead. This + // future proofs unit testing that assume that these are classes. + type.type._mockedReactClassConstructor = type; + } + args = Array.prototype.slice.call(arguments, 0); + args[0] = type.type; + return createElement.apply(this, args); + } + + if ("production" !== "development") { + warnForPlainFunctionType(type); + } + + // This is being called with a plain function we should invoke it + // immediately as if this was used with legacy JSX. + return type.apply(null, Array.prototype.slice.call(arguments, 1)); + }; + return legacyCreateElement; +}; + +ReactLegacyElementFactory.wrapFactory = function(factory) { + ("production" !== "development" ? invariant( + typeof factory === 'function', + 'This is suppose to accept a element factory' + ) : invariant(typeof factory === 'function')); + var legacyElementFactory = function(config, children) { + // This factory should not be called when JSX is used. Use JSX instead. + if ("production" !== "development") { + warnForLegacyFactoryCall(); + } + return factory.apply(this, arguments); + }; + proxyStaticMethods(legacyElementFactory, factory.type); + legacyElementFactory.isReactLegacyFactory = LEGACY_MARKER; + legacyElementFactory.type = factory.type; + return legacyElementFactory; +}; + +// This is used to mark a factory that will remain. E.g. we're allowed to call +// it as a function. However, you're not suppose to pass it to createElement +// or createFactory, so it will warn you if you do. +ReactLegacyElementFactory.markNonLegacyFactory = function(factory) { + factory.isReactNonLegacyFactory = NON_LEGACY_MARKER; + return factory; +}; + +// Checks if a factory function is actually a legacy factory pretending to +// be a class. +ReactLegacyElementFactory.isValidFactory = function(factory) { + // TODO: This will be removed and moved into a class validator or something. + return typeof factory === 'function' && + factory.isReactLegacyFactory === LEGACY_MARKER; +}; + +ReactLegacyElementFactory.isValidClass = function(factory) { + if ("production" !== "development") { + ("production" !== "development" ? warning( + false, + 'isValidClass is deprecated and will be removed in a future release. ' + + 'Use a more specific validator instead.' + ) : null); + } + return ReactLegacyElementFactory.isValidFactory(factory); +}; + +ReactLegacyElementFactory._isLegacyCallWarningEnabled = true; + +module.exports = ReactLegacyElementFactory; + +},{"./ReactCurrentOwner":42,"./invariant":140,"./monitorCodeUse":150,"./warning":160}],68:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactLink * @typechecks static-only @@ -11287,21 +11410,14 @@ ReactLink.PropTypes = { module.exports = ReactLink; -},{"./React":29}],66:[function(_dereq_,module,exports){ +},{"./React":31}],69:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactMarkupChecksum */ @@ -11342,21 +11458,14 @@ var ReactMarkupChecksum = { module.exports = ReactMarkupChecksum; -},{"./adler32":107}],67:[function(_dereq_,module,exports){ +},{"./adler32":110}],70:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactMount */ @@ -11366,17 +11475,23 @@ module.exports = ReactMarkupChecksum; var DOMProperty = _dereq_("./DOMProperty"); var ReactBrowserEventEmitter = _dereq_("./ReactBrowserEventEmitter"); var ReactCurrentOwner = _dereq_("./ReactCurrentOwner"); -var ReactDescriptor = _dereq_("./ReactDescriptor"); +var ReactElement = _dereq_("./ReactElement"); +var ReactLegacyElement = _dereq_("./ReactLegacyElement"); var ReactInstanceHandles = _dereq_("./ReactInstanceHandles"); var ReactPerf = _dereq_("./ReactPerf"); var containsNode = _dereq_("./containsNode"); +var deprecated = _dereq_("./deprecated"); var getReactRootElementInContainer = _dereq_("./getReactRootElementInContainer"); var instantiateReactComponent = _dereq_("./instantiateReactComponent"); var invariant = _dereq_("./invariant"); var shouldUpdateReactComponent = _dereq_("./shouldUpdateReactComponent"); var warning = _dereq_("./warning"); +var createElement = ReactLegacyElement.wrapCreateElement( + ReactElement.createElement +); + var SEPARATOR = ReactInstanceHandles.SEPARATOR; var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME; @@ -11544,7 +11659,7 @@ function findDeepestCachedAncestor(targetID) { * representative DOM elements and inserting them into a supplied `container`. * Any prior content inside `container` is destroyed in the process. * - * ReactMount.renderComponent( + * ReactMount.render( * component, * document.getElementById('container') * ); @@ -11650,7 +11765,7 @@ var ReactMount = { 'componentDidUpdate.' ) : null); - var componentInstance = instantiateReactComponent(nextComponent); + var componentInstance = instantiateReactComponent(nextComponent, null); var reactRootID = ReactMount._registerComponent( componentInstance, container @@ -11678,35 +11793,38 @@ var ReactMount = { * perform an update on it and only mutate the DOM as necessary to reflect the * latest React component. * - * @param {ReactDescriptor} nextDescriptor Component descriptor to render. + * @param {ReactElement} nextElement Component element to render. * @param {DOMElement} container DOM element to render into. * @param {?function} callback function triggered on completion * @return {ReactComponent} Component instance rendered in `container`. */ - renderComponent: function(nextDescriptor, container, callback) { + render: function(nextElement, container, callback) { ("production" !== "development" ? invariant( - ReactDescriptor.isValidDescriptor(nextDescriptor), - 'renderComponent(): Invalid component descriptor.%s', + ReactElement.isValidElement(nextElement), + 'renderComponent(): Invalid component element.%s', ( - ReactDescriptor.isValidFactory(nextDescriptor) ? + typeof nextElement === 'string' ? + ' Instead of passing an element string, make sure to instantiate ' + + 'it by passing it to React.createElement.' : + ReactLegacyElement.isValidFactory(nextElement) ? ' Instead of passing a component class, make sure to instantiate ' + - 'it first by calling it with props.' : - // Check if it quacks like a descriptor - typeof nextDescriptor.props !== "undefined" ? + 'it by passing it to React.createElement.' : + // Check if it quacks like a element + typeof nextElement.props !== "undefined" ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '' ) - ) : invariant(ReactDescriptor.isValidDescriptor(nextDescriptor))); + ) : invariant(ReactElement.isValidElement(nextElement))); var prevComponent = instancesByReactRootID[getReactRootID(container)]; if (prevComponent) { - var prevDescriptor = prevComponent._descriptor; - if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) { + var prevElement = prevComponent._currentElement; + if (shouldUpdateReactComponent(prevElement, nextElement)) { return ReactMount._updateRootComponent( prevComponent, - nextDescriptor, + nextElement, container, callback ); @@ -11722,7 +11840,7 @@ var ReactMount = { var shouldReuseMarkup = containerHasReactMarkup && !prevComponent; var component = ReactMount._renderNewRootComponent( - nextDescriptor, + nextElement, container, shouldReuseMarkup ); @@ -11740,7 +11858,8 @@ var ReactMount = { * @return {ReactComponent} Component instance rendered in `container`. */ constructAndRenderComponent: function(constructor, props, container) { - return ReactMount.renderComponent(constructor(props), container); + var element = createElement(constructor, props); + return ReactMount.render(element, container); }, /** @@ -11999,9 +12118,10 @@ var ReactMount = { false, 'findComponentRoot(..., %s): Unable to find element. This probably ' + 'means the DOM was unexpectedly mutated (e.g., by the browser), ' + - 'usually due to forgetting a <tbody> when using tables, nesting <p> ' + - 'or <a> tags, or using non-SVG elements in an <svg> parent. Try ' + - 'inspecting the child nodes of the element with React ID `%s`.', + 'usually due to forgetting a <tbody> when using tables, nesting tags ' + + 'like <form>, <p>, or <a>, or using non-SVG elements in an <svg> ' + + 'parent. ' + + 'Try inspecting the child nodes of the element with React ID `%s`.', targetID, ReactMount.getID(ancestorNode) ) : invariant(false)); @@ -12023,23 +12143,25 @@ var ReactMount = { purgeID: purgeID }; +// Deprecations (remove for 0.13) +ReactMount.renderComponent = deprecated( + 'ReactMount', + 'renderComponent', + 'render', + this, + ReactMount.render +); + module.exports = ReactMount; -},{"./DOMProperty":11,"./ReactBrowserEventEmitter":31,"./ReactCurrentOwner":40,"./ReactDescriptor":56,"./ReactInstanceHandles":64,"./ReactPerf":71,"./containsNode":109,"./getReactRootElementInContainer":128,"./instantiateReactComponent":133,"./invariant":134,"./shouldUpdateReactComponent":154,"./warning":158}],68:[function(_dereq_,module,exports){ +},{"./DOMProperty":12,"./ReactBrowserEventEmitter":33,"./ReactCurrentOwner":42,"./ReactElement":58,"./ReactInstanceHandles":66,"./ReactLegacyElement":67,"./ReactPerf":75,"./containsNode":114,"./deprecated":120,"./getReactRootElementInContainer":134,"./instantiateReactComponent":139,"./invariant":140,"./shouldUpdateReactComponent":156,"./warning":160}],71:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactMultiChild * @typechecks static-only @@ -12223,7 +12345,7 @@ var ReactMultiChild = { if (children.hasOwnProperty(name)) { // The rendered children must be turned into instances as they're // mounted. - var childInstance = instantiateReactComponent(child); + var childInstance = instantiateReactComponent(child, null); children[name] = childInstance; // Inlined for performance, see `ReactInstanceHandles.createReactID`. var rootID = this._rootNodeID + name; @@ -12314,12 +12436,12 @@ var ReactMultiChild = { continue; } var prevChild = prevChildren && prevChildren[name]; - var prevDescriptor = prevChild && prevChild._descriptor; - var nextDescriptor = nextChildren[name]; - if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) { + var prevElement = prevChild && prevChild._currentElement; + var nextElement = nextChildren[name]; + if (shouldUpdateReactComponent(prevElement, nextElement)) { this.moveChild(prevChild, nextIndex, lastIndex); lastIndex = Math.max(prevChild._mountIndex, lastIndex); - prevChild.receiveComponent(nextDescriptor, transaction); + prevChild.receiveComponent(nextElement, transaction); prevChild._mountIndex = nextIndex; } else { if (prevChild) { @@ -12328,7 +12450,10 @@ var ReactMultiChild = { this._unmountChildByName(prevChild, name); } // The child must be instantiated before it's mounted. - var nextChildInstance = instantiateReactComponent(nextDescriptor); + var nextChildInstance = instantiateReactComponent( + nextElement, + null + ); this._mountChildByNameAtIndex( nextChildInstance, name, nextIndex, transaction ); @@ -12457,21 +12582,14 @@ var ReactMultiChild = { module.exports = ReactMultiChild; -},{"./ReactComponent":35,"./ReactMultiChildUpdateTypes":69,"./flattenChildren":119,"./instantiateReactComponent":133,"./shouldUpdateReactComponent":154}],69:[function(_dereq_,module,exports){ +},{"./ReactComponent":37,"./ReactMultiChildUpdateTypes":72,"./flattenChildren":124,"./instantiateReactComponent":139,"./shouldUpdateReactComponent":156}],72:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactMultiChildUpdateTypes */ @@ -12497,21 +12615,85 @@ var ReactMultiChildUpdateTypes = keyMirror({ module.exports = ReactMultiChildUpdateTypes; -},{"./keyMirror":140}],70:[function(_dereq_,module,exports){ +},{"./keyMirror":146}],73:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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 + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * - * http://www.apache.org/licenses/LICENSE-2.0 + * @providesModule ReactNativeComponent + */ + +"use strict"; + +var assign = _dereq_("./Object.assign"); +var invariant = _dereq_("./invariant"); + +var genericComponentClass = null; +// This registry keeps track of wrapper classes around native tags +var tagToComponentClass = {}; + +var ReactNativeComponentInjection = { + // This accepts a class that receives the tag string. This is a catch all + // that can render any kind of tag. + injectGenericComponentClass: function(componentClass) { + genericComponentClass = componentClass; + }, + // This accepts a keyed object with classes as values. Each key represents a + // tag. That particular tag will use this class instead of the generic one. + injectComponentClasses: function(componentClasses) { + assign(tagToComponentClass, componentClasses); + } +}; + +/** + * Create an internal class for a specific tag. * - * 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. + * @param {string} tag The tag for which to create an internal instance. + * @param {any} props The props passed to the instance constructor. + * @return {ReactComponent} component The injected empty component. + */ +function createInstanceForTag(tag, props, parentType) { + var componentClass = tagToComponentClass[tag]; + if (componentClass == null) { + ("production" !== "development" ? invariant( + genericComponentClass, + 'There is no registered component for the tag %s', + tag + ) : invariant(genericComponentClass)); + return new genericComponentClass(tag, props); + } + if (parentType === tag) { + // Avoid recursion + ("production" !== "development" ? invariant( + genericComponentClass, + 'There is no registered component for the tag %s', + tag + ) : invariant(genericComponentClass)); + return new genericComponentClass(tag, props); + } + // Unwrap legacy factories + return new componentClass.type(props); +} + +var ReactNativeComponent = { + createInstanceForTag: createInstanceForTag, + injection: ReactNativeComponentInjection +}; + +module.exports = ReactNativeComponent; + +},{"./Object.assign":29,"./invariant":140}],74:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactOwner */ @@ -12658,21 +12840,14 @@ var ReactOwner = { module.exports = ReactOwner; -},{"./emptyObject":117,"./invariant":134}],71:[function(_dereq_,module,exports){ +},{"./emptyObject":122,"./invariant":140}],75:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactPerf * @typechecks static-only @@ -12708,7 +12883,7 @@ var ReactPerf = { measure: function(objName, fnName, func) { if ("production" !== "development") { var measuredFunc = null; - return function() { + var wrapper = function() { if (ReactPerf.enableMeasure) { if (!measuredFunc) { measuredFunc = ReactPerf.storedMeasure(objName, fnName, func); @@ -12717,6 +12892,8 @@ var ReactPerf = { } return func.apply(this, arguments); }; + wrapper.displayName = objName + '_' + fnName; + return wrapper; } return func; }, @@ -12745,31 +12922,27 @@ function _noMeasure(objName, fnName, func) { module.exports = ReactPerf; -},{}],72:[function(_dereq_,module,exports){ +},{}],76:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactPropTransferer */ "use strict"; +var assign = _dereq_("./Object.assign"); var emptyFunction = _dereq_("./emptyFunction"); var invariant = _dereq_("./invariant"); var joinClasses = _dereq_("./joinClasses"); -var merge = _dereq_("./merge"); +var warning = _dereq_("./warning"); + +var didWarn = false; /** * Creates a transfer strategy that will merge prop values using the supplied @@ -12792,7 +12965,7 @@ var transferStrategyMerge = createTransferStrategy(function(a, b) { // `merge` overrides the first object's (`props[key]` above) keys using the // second object's (`value`) keys. An object's style's existing `propA` would // get overridden. Flip the order here. - return merge(b, a); + return assign({}, b, a); }); /** @@ -12810,14 +12983,6 @@ var TransferStrategies = { */ className: createTransferStrategy(joinClasses), /** - * Never transfer the `key` prop. - */ - key: emptyFunction, - /** - * Never transfer the `ref` prop. - */ - ref: emptyFunction, - /** * Transfer the `style` prop (which is an object) by merging them. */ style: transferStrategyMerge @@ -12866,7 +13031,7 @@ var ReactPropTransferer = { * @return {object} a new object containing both sets of props merged. */ mergeProps: function(oldProps, newProps) { - return transferInto(merge(oldProps), newProps); + return transferInto(assign({}, oldProps), newProps); }, /** @@ -12882,26 +13047,39 @@ var ReactPropTransferer = { * * This is usually used to pass down props to a returned root component. * - * @param {ReactDescriptor} descriptor Component receiving the properties. - * @return {ReactDescriptor} The supplied `component`. + * @param {ReactElement} element Component receiving the properties. + * @return {ReactElement} The supplied `component`. * @final * @protected */ - transferPropsTo: function(descriptor) { + transferPropsTo: function(element) { ("production" !== "development" ? invariant( - descriptor._owner === this, + element._owner === this, '%s: You can\'t call transferPropsTo() on a component that you ' + 'don\'t own, %s. This usually means you are calling ' + 'transferPropsTo() on a component passed in as props or children.', this.constructor.displayName, - descriptor.type.displayName - ) : invariant(descriptor._owner === this)); + typeof element.type === 'string' ? + element.type : + element.type.displayName + ) : invariant(element._owner === this)); + + if ("production" !== "development") { + if (!didWarn) { + didWarn = true; + ("production" !== "development" ? warning( + false, + 'transferPropsTo is deprecated. ' + + 'See http://fb.me/react-transferpropsto for more information.' + ) : null); + } + } - // Because descriptors are immutable we have to merge into the existing + // Because elements are immutable we have to merge into the existing // props object rather than clone it. - transferInto(descriptor.props, this.props); + transferInto(element.props, this.props); - return descriptor; + return element; } } @@ -12909,21 +13087,14 @@ var ReactPropTransferer = { module.exports = ReactPropTransferer; -},{"./emptyFunction":116,"./invariant":134,"./joinClasses":139,"./merge":144}],73:[function(_dereq_,module,exports){ +},{"./Object.assign":29,"./emptyFunction":121,"./invariant":140,"./joinClasses":145,"./warning":160}],77:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactPropTypeLocationNames */ @@ -12942,21 +13113,14 @@ if ("production" !== "development") { module.exports = ReactPropTypeLocationNames; -},{}],74:[function(_dereq_,module,exports){ +},{}],78:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactPropTypeLocations */ @@ -12973,30 +13137,24 @@ var ReactPropTypeLocations = keyMirror({ module.exports = ReactPropTypeLocations; -},{"./keyMirror":140}],75:[function(_dereq_,module,exports){ +},{"./keyMirror":146}],79:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactPropTypes */ "use strict"; -var ReactDescriptor = _dereq_("./ReactDescriptor"); +var ReactElement = _dereq_("./ReactElement"); var ReactPropTypeLocationNames = _dereq_("./ReactPropTypeLocationNames"); +var deprecated = _dereq_("./deprecated"); var emptyFunction = _dereq_("./emptyFunction"); /** @@ -13048,6 +13206,9 @@ var emptyFunction = _dereq_("./emptyFunction"); var ANONYMOUS = '<<anonymous>>'; +var elementTypeChecker = createElementTypeChecker(); +var nodeTypeChecker = createNodeChecker(); + var ReactPropTypes = { array: createPrimitiveTypeChecker('array'), bool: createPrimitiveTypeChecker('boolean'), @@ -13058,13 +13219,28 @@ var ReactPropTypes = { any: createAnyTypeChecker(), arrayOf: createArrayOfTypeChecker, - component: createComponentTypeChecker(), + element: elementTypeChecker, instanceOf: createInstanceTypeChecker, + node: nodeTypeChecker, objectOf: createObjectOfTypeChecker, oneOf: createEnumTypeChecker, oneOfType: createUnionTypeChecker, - renderable: createRenderableTypeChecker(), - shape: createShapeTypeChecker + shape: createShapeTypeChecker, + + component: deprecated( + 'React.PropTypes', + 'component', + 'element', + this, + elementTypeChecker + ), + renderable: deprecated( + 'React.PropTypes', + 'renderable', + 'node', + this, + nodeTypeChecker + ) }; function createChainableTypeChecker(validate) { @@ -13134,13 +13310,13 @@ function createArrayOfTypeChecker(typeChecker) { return createChainableTypeChecker(validate); } -function createComponentTypeChecker() { +function createElementTypeChecker() { function validate(props, propName, componentName, location) { - if (!ReactDescriptor.isValidDescriptor(props[propName])) { + if (!ReactElement.isValidElement(props[propName])) { var locationName = ReactPropTypeLocationNames[location]; return new Error( ("Invalid " + locationName + " `" + propName + "` supplied to ") + - ("`" + componentName + "`, expected a React component.") + ("`" + componentName + "`, expected a ReactElement.") ); } } @@ -13221,13 +13397,13 @@ function createUnionTypeChecker(arrayOfTypeCheckers) { return createChainableTypeChecker(validate); } -function createRenderableTypeChecker() { +function createNodeChecker() { function validate(props, propName, componentName, location) { - if (!isRenderable(props[propName])) { + if (!isNode(props[propName])) { var locationName = ReactPropTypeLocationNames[location]; return new Error( ("Invalid " + locationName + " `" + propName + "` supplied to ") + - ("`" + componentName + "`, expected a renderable prop.") + ("`" + componentName + "`, expected a ReactNode.") ); } } @@ -13259,11 +13435,8 @@ function createShapeTypeChecker(shapeTypes) { return createChainableTypeChecker(validate, 'expected `object`'); } -function isRenderable(propValue) { +function isNode(propValue) { switch(typeof propValue) { - // TODO: this was probably written with the assumption that we're not - // returning `this.props.component` directly from `render`. This is - // currently not supported but we should, to make it consistent. case 'number': case 'string': return true; @@ -13271,13 +13444,13 @@ function isRenderable(propValue) { return !propValue; case 'object': if (Array.isArray(propValue)) { - return propValue.every(isRenderable); + return propValue.every(isNode); } - if (ReactDescriptor.isValidDescriptor(propValue)) { + if (ReactElement.isValidElement(propValue)) { return true; } for (var k in propValue) { - if (!isRenderable(propValue[k])) { + if (!isNode(propValue[k])) { return false; } } @@ -13318,21 +13491,14 @@ function getPreciseType(propValue) { module.exports = ReactPropTypes; -},{"./ReactDescriptor":56,"./ReactPropTypeLocationNames":73,"./emptyFunction":116}],76:[function(_dereq_,module,exports){ +},{"./ReactElement":58,"./ReactPropTypeLocationNames":77,"./deprecated":120,"./emptyFunction":121}],80:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactPutListenerQueue */ @@ -13342,13 +13508,13 @@ module.exports = ReactPropTypes; var PooledClass = _dereq_("./PooledClass"); var ReactBrowserEventEmitter = _dereq_("./ReactBrowserEventEmitter"); -var mixInto = _dereq_("./mixInto"); +var assign = _dereq_("./Object.assign"); function ReactPutListenerQueue() { this.listenersToPut = []; } -mixInto(ReactPutListenerQueue, { +assign(ReactPutListenerQueue.prototype, { enqueuePutListener: function(rootNodeID, propKey, propValue) { this.listenersToPut.push({ rootNodeID: rootNodeID, @@ -13381,21 +13547,14 @@ PooledClass.addPoolingTo(ReactPutListenerQueue); module.exports = ReactPutListenerQueue; -},{"./PooledClass":28,"./ReactBrowserEventEmitter":31,"./mixInto":147}],77:[function(_dereq_,module,exports){ +},{"./Object.assign":29,"./PooledClass":30,"./ReactBrowserEventEmitter":33}],81:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactReconcileTransaction * @typechecks static-only @@ -13410,7 +13569,7 @@ var ReactInputSelection = _dereq_("./ReactInputSelection"); var ReactPutListenerQueue = _dereq_("./ReactPutListenerQueue"); var Transaction = _dereq_("./Transaction"); -var mixInto = _dereq_("./mixInto"); +var assign = _dereq_("./Object.assign"); /** * Ensures that, when possible, the selection range (currently selected text @@ -13558,28 +13717,20 @@ var Mixin = { }; -mixInto(ReactReconcileTransaction, Transaction.Mixin); -mixInto(ReactReconcileTransaction, Mixin); +assign(ReactReconcileTransaction.prototype, Transaction.Mixin, Mixin); PooledClass.addPoolingTo(ReactReconcileTransaction); module.exports = ReactReconcileTransaction; -},{"./CallbackQueue":6,"./PooledClass":28,"./ReactBrowserEventEmitter":31,"./ReactInputSelection":63,"./ReactPutListenerQueue":76,"./Transaction":104,"./mixInto":147}],78:[function(_dereq_,module,exports){ +},{"./CallbackQueue":7,"./Object.assign":29,"./PooledClass":30,"./ReactBrowserEventEmitter":33,"./ReactInputSelection":65,"./ReactPutListenerQueue":80,"./Transaction":107}],82:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactRootIndex * @typechecks @@ -13603,28 +13754,21 @@ var ReactRootIndex = { module.exports = ReactRootIndex; -},{}],79:[function(_dereq_,module,exports){ +},{}],83:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @typechecks static-only * @providesModule ReactServerRendering */ "use strict"; -var ReactDescriptor = _dereq_("./ReactDescriptor"); +var ReactElement = _dereq_("./ReactElement"); var ReactInstanceHandles = _dereq_("./ReactInstanceHandles"); var ReactMarkupChecksum = _dereq_("./ReactMarkupChecksum"); var ReactServerRenderingTransaction = @@ -13634,20 +13778,14 @@ var instantiateReactComponent = _dereq_("./instantiateReactComponent"); var invariant = _dereq_("./invariant"); /** - * @param {ReactComponent} component + * @param {ReactElement} element * @return {string} the HTML markup */ -function renderComponentToString(component) { +function renderToString(element) { ("production" !== "development" ? invariant( - ReactDescriptor.isValidDescriptor(component), - 'renderComponentToString(): You must pass a valid ReactComponent.' - ) : invariant(ReactDescriptor.isValidDescriptor(component))); - - ("production" !== "development" ? invariant( - !(arguments.length === 2 && typeof arguments[1] === 'function'), - 'renderComponentToString(): This function became synchronous and now ' + - 'returns the generated markup. Please remove the second parameter.' - ) : invariant(!(arguments.length === 2 && typeof arguments[1] === 'function'))); + ReactElement.isValidElement(element), + 'renderToString(): You must pass a valid ReactElement.' + ) : invariant(ReactElement.isValidElement(element))); var transaction; try { @@ -13655,7 +13793,7 @@ function renderComponentToString(component) { transaction = ReactServerRenderingTransaction.getPooled(false); return transaction.perform(function() { - var componentInstance = instantiateReactComponent(component); + var componentInstance = instantiateReactComponent(element, null); var markup = componentInstance.mountComponent(id, transaction, 0); return ReactMarkupChecksum.addChecksumToMarkup(markup); }, null); @@ -13665,15 +13803,15 @@ function renderComponentToString(component) { } /** - * @param {ReactComponent} component + * @param {ReactElement} element * @return {string} the HTML markup, without the extra React ID and checksum -* (for generating static pages) + * (for generating static pages) */ -function renderComponentToStaticMarkup(component) { +function renderToStaticMarkup(element) { ("production" !== "development" ? invariant( - ReactDescriptor.isValidDescriptor(component), - 'renderComponentToStaticMarkup(): You must pass a valid ReactComponent.' - ) : invariant(ReactDescriptor.isValidDescriptor(component))); + ReactElement.isValidElement(element), + 'renderToStaticMarkup(): You must pass a valid ReactElement.' + ) : invariant(ReactElement.isValidElement(element))); var transaction; try { @@ -13681,7 +13819,7 @@ function renderComponentToStaticMarkup(component) { transaction = ReactServerRenderingTransaction.getPooled(true); return transaction.perform(function() { - var componentInstance = instantiateReactComponent(component); + var componentInstance = instantiateReactComponent(element, null); return componentInstance.mountComponent(id, transaction, 0); }, null); } finally { @@ -13690,25 +13828,18 @@ function renderComponentToStaticMarkup(component) { } module.exports = { - renderComponentToString: renderComponentToString, - renderComponentToStaticMarkup: renderComponentToStaticMarkup + renderToString: renderToString, + renderToStaticMarkup: renderToStaticMarkup }; -},{"./ReactDescriptor":56,"./ReactInstanceHandles":64,"./ReactMarkupChecksum":66,"./ReactServerRenderingTransaction":80,"./instantiateReactComponent":133,"./invariant":134}],80:[function(_dereq_,module,exports){ +},{"./ReactElement":58,"./ReactInstanceHandles":66,"./ReactMarkupChecksum":69,"./ReactServerRenderingTransaction":84,"./instantiateReactComponent":139,"./invariant":140}],84:[function(_dereq_,module,exports){ /** - * Copyright 2014 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 + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactServerRenderingTransaction * @typechecks @@ -13721,8 +13852,8 @@ var CallbackQueue = _dereq_("./CallbackQueue"); var ReactPutListenerQueue = _dereq_("./ReactPutListenerQueue"); var Transaction = _dereq_("./Transaction"); +var assign = _dereq_("./Object.assign"); var emptyFunction = _dereq_("./emptyFunction"); -var mixInto = _dereq_("./mixInto"); /** * Provides a `CallbackQueue` queue for collecting `onDOMReady` callbacks @@ -13804,28 +13935,24 @@ var Mixin = { }; -mixInto(ReactServerRenderingTransaction, Transaction.Mixin); -mixInto(ReactServerRenderingTransaction, Mixin); +assign( + ReactServerRenderingTransaction.prototype, + Transaction.Mixin, + Mixin +); PooledClass.addPoolingTo(ReactServerRenderingTransaction); module.exports = ReactServerRenderingTransaction; -},{"./CallbackQueue":6,"./PooledClass":28,"./ReactPutListenerQueue":76,"./Transaction":104,"./emptyFunction":116,"./mixInto":147}],81:[function(_dereq_,module,exports){ +},{"./CallbackQueue":7,"./Object.assign":29,"./PooledClass":30,"./ReactPutListenerQueue":80,"./Transaction":107,"./emptyFunction":121}],85:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactStateSetters */ @@ -13924,21 +14051,14 @@ ReactStateSetters.Mixin = { module.exports = ReactStateSetters; -},{}],82:[function(_dereq_,module,exports){ +},{}],86:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactTestUtils */ @@ -13949,16 +14069,14 @@ var EventConstants = _dereq_("./EventConstants"); var EventPluginHub = _dereq_("./EventPluginHub"); var EventPropagators = _dereq_("./EventPropagators"); var React = _dereq_("./React"); -var ReactDescriptor = _dereq_("./ReactDescriptor"); -var ReactDOM = _dereq_("./ReactDOM"); +var ReactElement = _dereq_("./ReactElement"); var ReactBrowserEventEmitter = _dereq_("./ReactBrowserEventEmitter"); var ReactMount = _dereq_("./ReactMount"); var ReactTextComponent = _dereq_("./ReactTextComponent"); var ReactUpdates = _dereq_("./ReactUpdates"); var SyntheticEvent = _dereq_("./SyntheticEvent"); -var mergeInto = _dereq_("./mergeInto"); -var copyProperties = _dereq_("./copyProperties"); +var assign = _dereq_("./Object.assign"); var topLevelTypes = EventConstants.topLevelTypes; @@ -13981,16 +14099,16 @@ var ReactTestUtils = { // clean up, so we're going to stop honoring the name of this method // (and probably rename it eventually) if no problems arise. // document.documentElement.appendChild(div); - return React.renderComponent(instance, div); + return React.render(instance, div); }, - isDescriptor: function(descriptor) { - return ReactDescriptor.isValidDescriptor(descriptor); + isElement: function(element) { + return ReactElement.isValidElement(element); }, - isDescriptorOfType: function(inst, convenienceConstructor) { + isElementOfType: function(inst, convenienceConstructor) { return ( - ReactDescriptor.isValidDescriptor(inst) && + ReactElement.isValidElement(inst) && inst.type === convenienceConstructor.type ); }, @@ -13999,9 +14117,9 @@ var ReactTestUtils = { return !!(inst && inst.mountComponent && inst.tagName); }, - isDOMComponentDescriptor: function(inst) { + isDOMComponentElement: function(inst) { return !!(inst && - ReactDescriptor.isValidDescriptor(inst) && + ReactElement.isValidElement(inst) && !!inst.tagName); }, @@ -14015,8 +14133,8 @@ var ReactTestUtils = { (inst.constructor === type.type)); }, - isCompositeComponentDescriptor: function(inst) { - if (!ReactDescriptor.isValidDescriptor(inst)) { + isCompositeComponentElement: function(inst) { + if (!ReactElement.isValidElement(inst)) { return false; } // We check the prototype of the type that will get mounted, not the @@ -14028,8 +14146,8 @@ var ReactTestUtils = { ); }, - isCompositeComponentDescriptorWithType: function(inst, type) { - return !!(ReactTestUtils.isCompositeComponentDescriptor(inst) && + isCompositeComponentElementWithType: function(inst, type) { + return !!(ReactTestUtils.isCompositeComponentElement(inst) && (inst.constructor === type)); }, @@ -14165,16 +14283,23 @@ var ReactTestUtils = { * @return {object} the ReactTestUtils object (for chaining) */ mockComponent: function(module, mockTagName) { - var ConvenienceConstructor = React.createClass({ + mockTagName = mockTagName || module.mockTagName || "div"; + + var ConvenienceConstructor = React.createClass({displayName: 'ConvenienceConstructor', render: function() { - var mockTagName = mockTagName || module.mockTagName || "div"; - return ReactDOM[mockTagName](null, this.props.children); + return React.createElement( + mockTagName, + null, + this.props.children + ); } }); - copyProperties(module, ConvenienceConstructor); module.mockImplementation(ConvenienceConstructor); + module.type = ConvenienceConstructor.type; + module.isReactLegacyFactory = true; + return this; }, @@ -14249,7 +14374,7 @@ function makeSimulator(eventType) { ReactMount.getID(node), fakeNativeEvent ); - mergeInto(event, eventData); + assign(event, eventData); EventPropagators.accumulateTwoPhaseDispatches(event); ReactUpdates.batchedUpdates(function() { @@ -14305,7 +14430,7 @@ buildSimulators(); function makeNativeSimulator(eventType) { return function(domComponentOrNode, nativeEventData) { var fakeNativeEvent = new Event(eventType); - mergeInto(fakeNativeEvent, nativeEventData); + assign(fakeNativeEvent, nativeEventData); if (ReactTestUtils.isDOMComponent(domComponentOrNode)) { ReactTestUtils.simulateNativeEventOnDOMComponent( eventType, @@ -14338,21 +14463,14 @@ for (eventType in topLevelTypes) { module.exports = ReactTestUtils; -},{"./EventConstants":16,"./EventPluginHub":18,"./EventPropagators":21,"./React":29,"./ReactBrowserEventEmitter":31,"./ReactDOM":41,"./ReactDescriptor":56,"./ReactMount":67,"./ReactTextComponent":83,"./ReactUpdates":87,"./SyntheticEvent":96,"./copyProperties":110,"./mergeInto":146}],83:[function(_dereq_,module,exports){ +},{"./EventConstants":17,"./EventPluginHub":19,"./EventPropagators":22,"./Object.assign":29,"./React":31,"./ReactBrowserEventEmitter":33,"./ReactElement":58,"./ReactMount":70,"./ReactTextComponent":87,"./ReactUpdates":91,"./SyntheticEvent":99}],87:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactTextComponent * @typechecks static-only @@ -14361,12 +14479,11 @@ module.exports = ReactTestUtils; "use strict"; var DOMPropertyOperations = _dereq_("./DOMPropertyOperations"); -var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); var ReactComponent = _dereq_("./ReactComponent"); -var ReactDescriptor = _dereq_("./ReactDescriptor"); +var ReactElement = _dereq_("./ReactElement"); +var assign = _dereq_("./Object.assign"); var escapeTextForBrowser = _dereq_("./escapeTextForBrowser"); -var mixInto = _dereq_("./mixInto"); /** * Text nodes violate a couple assumptions that React makes about components: @@ -14383,13 +14500,11 @@ var mixInto = _dereq_("./mixInto"); * @extends ReactComponent * @internal */ -var ReactTextComponent = function(descriptor) { - this.construct(descriptor); +var ReactTextComponent = function(props) { + // This constructor and it's argument is currently used by mocks. }; -mixInto(ReactTextComponent, ReactComponent.Mixin); -mixInto(ReactTextComponent, ReactBrowserComponentMixin); -mixInto(ReactTextComponent, { +assign(ReactTextComponent.prototype, ReactComponent.Mixin, { /** * Creates the markup for this text node. This node is not intended to have @@ -14445,23 +14560,23 @@ mixInto(ReactTextComponent, { }); -module.exports = ReactDescriptor.createFactory(ReactTextComponent); +var ReactTextComponentFactory = function(text) { + // Bypass validation and configuration + return new ReactElement(ReactTextComponent, null, null, null, null, text); +}; + +ReactTextComponentFactory.type = ReactTextComponent; + +module.exports = ReactTextComponentFactory; -},{"./DOMPropertyOperations":12,"./ReactBrowserComponentMixin":30,"./ReactComponent":35,"./ReactDescriptor":56,"./escapeTextForBrowser":118,"./mixInto":147}],84:[function(_dereq_,module,exports){ +},{"./DOMPropertyOperations":13,"./Object.assign":29,"./ReactComponent":37,"./ReactElement":58,"./escapeTextForBrowser":123}],88:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @typechecks static-only * @providesModule ReactTransitionChildMapping @@ -14487,7 +14602,7 @@ var ReactTransitionChildMapping = { /** * When you're adding or removing children some may be added or removed in the - * same render pass. We want ot show *both* since we want to simultaneously + * same render pass. We want to show *both* since we want to simultaneously * animate elements in and out. This function takes a previous set of keys * and a new set of keys and merges them with its best guess of the correct * ordering. In the future we may expose some of the utilities in @@ -14555,21 +14670,14 @@ var ReactTransitionChildMapping = { module.exports = ReactTransitionChildMapping; -},{"./ReactChildren":34}],85:[function(_dereq_,module,exports){ +},{"./ReactChildren":36}],89:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactTransitionEvents */ @@ -14673,21 +14781,14 @@ var ReactTransitionEvents = { module.exports = ReactTransitionEvents; -},{"./ExecutionEnvironment":22}],86:[function(_dereq_,module,exports){ +},{"./ExecutionEnvironment":23}],90:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactTransitionGroup */ @@ -14697,21 +14798,21 @@ module.exports = ReactTransitionEvents; var React = _dereq_("./React"); var ReactTransitionChildMapping = _dereq_("./ReactTransitionChildMapping"); +var assign = _dereq_("./Object.assign"); var cloneWithProps = _dereq_("./cloneWithProps"); var emptyFunction = _dereq_("./emptyFunction"); -var merge = _dereq_("./merge"); var ReactTransitionGroup = React.createClass({ displayName: 'ReactTransitionGroup', propTypes: { - component: React.PropTypes.func, + component: React.PropTypes.any, childFactory: React.PropTypes.func }, getDefaultProps: function() { return { - component: React.DOM.span, + component: 'span', childFactory: emptyFunction.thatReturnsArgument }; }, @@ -14835,7 +14936,7 @@ var ReactTransitionGroup = React.createClass({ // This entered again before it fully left. Add it again. this.performEnter(key); } else { - var newChildren = merge(this.state.children); + var newChildren = assign({}, this.state.children); delete newChildren[key]; this.setState({children: newChildren}); } @@ -14859,27 +14960,24 @@ var ReactTransitionGroup = React.createClass({ ); } } - return this.transferPropsTo(this.props.component(null, childrenToRender)); + return React.createElement( + this.props.component, + this.props, + childrenToRender + ); } }); module.exports = ReactTransitionGroup; -},{"./React":29,"./ReactTransitionChildMapping":84,"./cloneWithProps":108,"./emptyFunction":116,"./merge":144}],87:[function(_dereq_,module,exports){ +},{"./Object.assign":29,"./React":31,"./ReactTransitionChildMapping":88,"./cloneWithProps":113,"./emptyFunction":121}],91:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactUpdates */ @@ -14892,11 +14990,13 @@ var ReactCurrentOwner = _dereq_("./ReactCurrentOwner"); var ReactPerf = _dereq_("./ReactPerf"); var Transaction = _dereq_("./Transaction"); +var assign = _dereq_("./Object.assign"); var invariant = _dereq_("./invariant"); -var mixInto = _dereq_("./mixInto"); var warning = _dereq_("./warning"); var dirtyComponents = []; +var asapCallbackQueue = CallbackQueue.getPooled(); +var asapEnqueued = false; var batchingStrategy = null; @@ -14941,13 +15041,14 @@ var TRANSACTION_WRAPPERS = [NESTED_UPDATES, UPDATE_QUEUEING]; function ReactUpdatesFlushTransaction() { this.reinitializeTransaction(); this.dirtyComponentsLength = null; - this.callbackQueue = CallbackQueue.getPooled(null); + this.callbackQueue = CallbackQueue.getPooled(); this.reconcileTransaction = ReactUpdates.ReactReconcileTransaction.getPooled(); } -mixInto(ReactUpdatesFlushTransaction, Transaction.Mixin); -mixInto(ReactUpdatesFlushTransaction, { +assign( + ReactUpdatesFlushTransaction.prototype, + Transaction.Mixin, { getTransactionWrappers: function() { return TRANSACTION_WRAPPERS; }, @@ -15038,11 +15139,21 @@ var flushBatchedUpdates = ReactPerf.measure( // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents // array and perform any updates enqueued by mount-ready handlers (i.e., // componentDidUpdate) but we need to check here too in order to catch - // updates enqueued by setState callbacks. - while (dirtyComponents.length) { - var transaction = ReactUpdatesFlushTransaction.getPooled(); - transaction.perform(runBatchedUpdates, null, transaction); - ReactUpdatesFlushTransaction.release(transaction); + // updates enqueued by setState callbacks and asap calls. + while (dirtyComponents.length || asapEnqueued) { + if (dirtyComponents.length) { + var transaction = ReactUpdatesFlushTransaction.getPooled(); + transaction.perform(runBatchedUpdates, null, transaction); + ReactUpdatesFlushTransaction.release(transaction); + } + + if (asapEnqueued) { + asapEnqueued = false; + var queue = asapCallbackQueue; + asapCallbackQueue = CallbackQueue.getPooled(); + queue.notifyAll(); + CallbackQueue.release(queue); + } } } ); @@ -15089,6 +15200,20 @@ function enqueueUpdate(component, callback) { } } +/** + * Enqueue a callback to be run at the end of the current batching cycle. Throws + * if no updates are currently being performed. + */ +function asap(callback, context) { + ("production" !== "development" ? invariant( + batchingStrategy.isBatchingUpdates, + 'ReactUpdates.asap: Can\'t enqueue an asap callback in a context where' + + 'updates are not being batched.' + ) : invariant(batchingStrategy.isBatchingUpdates)); + asapCallbackQueue.enqueue(callback, context); + asapEnqueued = true; +} + var ReactUpdatesInjection = { injectReconcileTransaction: function(ReconcileTransaction) { ("production" !== "development" ? invariant( @@ -15127,84 +15252,20 @@ var ReactUpdates = { batchedUpdates: batchedUpdates, enqueueUpdate: enqueueUpdate, flushBatchedUpdates: flushBatchedUpdates, - injection: ReactUpdatesInjection + injection: ReactUpdatesInjection, + asap: asap }; module.exports = ReactUpdates; -},{"./CallbackQueue":6,"./PooledClass":28,"./ReactCurrentOwner":40,"./ReactPerf":71,"./Transaction":104,"./invariant":134,"./mixInto":147,"./warning":158}],88:[function(_dereq_,module,exports){ +},{"./CallbackQueue":7,"./Object.assign":29,"./PooledClass":30,"./ReactCurrentOwner":42,"./ReactPerf":75,"./Transaction":107,"./invariant":140,"./warning":160}],92:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. - * - * @providesModule ReactWithAddons - */ - -/** - * This module exists purely in the open source project, and is meant as a way - * to create a separate standalone build of React. This build has "addons", or - * functionality we've built and think might be useful but doesn't have a good - * place to live inside React core. - */ - -"use strict"; - -var LinkedStateMixin = _dereq_("./LinkedStateMixin"); -var React = _dereq_("./React"); -var ReactComponentWithPureRenderMixin = - _dereq_("./ReactComponentWithPureRenderMixin"); -var ReactCSSTransitionGroup = _dereq_("./ReactCSSTransitionGroup"); -var ReactTransitionGroup = _dereq_("./ReactTransitionGroup"); - -var cx = _dereq_("./cx"); -var cloneWithProps = _dereq_("./cloneWithProps"); -var update = _dereq_("./update"); - -React.addons = { - CSSTransitionGroup: ReactCSSTransitionGroup, - LinkedStateMixin: LinkedStateMixin, - PureRenderMixin: ReactComponentWithPureRenderMixin, - TransitionGroup: ReactTransitionGroup, - - classSet: cx, - cloneWithProps: cloneWithProps, - update: update -}; - -if ("production" !== "development") { - React.addons.Perf = _dereq_("./ReactDefaultPerf"); - React.addons.TestUtils = _dereq_("./ReactTestUtils"); -} - -module.exports = React; - - -},{"./LinkedStateMixin":24,"./React":29,"./ReactCSSTransitionGroup":32,"./ReactComponentWithPureRenderMixin":37,"./ReactDefaultPerf":54,"./ReactTestUtils":82,"./ReactTransitionGroup":86,"./cloneWithProps":108,"./cx":114,"./update":157}],89:[function(_dereq_,module,exports){ -/** - * Copyright 2013-2014 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SVGDOMPropertyConfig */ @@ -15289,21 +15350,14 @@ var SVGDOMPropertyConfig = { module.exports = SVGDOMPropertyConfig; -},{"./DOMProperty":11}],90:[function(_dereq_,module,exports){ +},{"./DOMProperty":12}],93:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SelectEventPlugin */ @@ -15361,6 +15415,14 @@ function getSelection(node) { start: node.selectionStart, end: node.selectionEnd }; + } else if (window.getSelection) { + var selection = window.getSelection(); + return { + anchorNode: selection.anchorNode, + anchorOffset: selection.anchorOffset, + focusNode: selection.focusNode, + focusOffset: selection.focusOffset + }; } else if (document.selection) { var range = document.selection.createRange(); return { @@ -15369,14 +15431,6 @@ function getSelection(node) { top: range.boundingTop, left: range.boundingLeft }; - } else { - var selection = window.getSelection(); - return { - anchorNode: selection.anchorNode, - anchorOffset: selection.anchorOffset, - focusNode: selection.focusNode, - focusOffset: selection.focusOffset - }; } } @@ -15491,21 +15545,14 @@ var SelectEventPlugin = { module.exports = SelectEventPlugin; -},{"./EventConstants":16,"./EventPropagators":21,"./ReactInputSelection":63,"./SyntheticEvent":96,"./getActiveElement":122,"./isTextInputElement":137,"./keyOf":141,"./shallowEqual":153}],91:[function(_dereq_,module,exports){ +},{"./EventConstants":17,"./EventPropagators":22,"./ReactInputSelection":65,"./SyntheticEvent":99,"./getActiveElement":127,"./isTextInputElement":143,"./keyOf":147,"./shallowEqual":155}],94:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ServerReactRootIndex * @typechecks @@ -15529,21 +15576,14 @@ var ServerReactRootIndex = { module.exports = ServerReactRootIndex; -},{}],92:[function(_dereq_,module,exports){ +},{}],95:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SimpleEventPlugin */ @@ -15563,8 +15603,11 @@ var SyntheticTouchEvent = _dereq_("./SyntheticTouchEvent"); var SyntheticUIEvent = _dereq_("./SyntheticUIEvent"); var SyntheticWheelEvent = _dereq_("./SyntheticWheelEvent"); +var getEventCharCode = _dereq_("./getEventCharCode"); + var invariant = _dereq_("./invariant"); var keyOf = _dereq_("./keyOf"); +var warning = _dereq_("./warning"); var topLevelTypes = EventConstants.topLevelTypes; @@ -15831,7 +15874,7 @@ var SimpleEventPlugin = { /** * Same as the default implementation, except cancels the event when return - * value is false. + * value is false. This behavior will be disabled in a future release. * * @param {object} Event to be dispatched. * @param {function} Application-level callback. @@ -15839,6 +15882,14 @@ var SimpleEventPlugin = { */ executeDispatch: function(event, listener, domID) { var returnValue = EventPluginUtils.executeDispatch(event, listener, domID); + + ("production" !== "development" ? warning( + typeof returnValue !== 'boolean', + 'Returning `false` from an event handler is deprecated and will be ' + + 'ignored in a future release. Instead, manually call ' + + 'e.stopPropagation() or e.preventDefault(), as appropriate.' + ) : null); + if (returnValue === false) { event.stopPropagation(); event.preventDefault(); @@ -15875,8 +15926,9 @@ var SimpleEventPlugin = { break; case topLevelTypes.topKeyPress: // FireFox creates a keypress event for function keys too. This removes - // the unwanted keypress events. - if (nativeEvent.charCode === 0) { + // the unwanted keypress events. Enter is however both printable and + // non-printable. One would expect Tab to be as well (but it isn't). + if (getEventCharCode(nativeEvent) === 0) { return null; } /* falls through */ @@ -15950,21 +16002,14 @@ var SimpleEventPlugin = { module.exports = SimpleEventPlugin; -},{"./EventConstants":16,"./EventPluginUtils":20,"./EventPropagators":21,"./SyntheticClipboardEvent":93,"./SyntheticDragEvent":95,"./SyntheticEvent":96,"./SyntheticFocusEvent":97,"./SyntheticKeyboardEvent":99,"./SyntheticMouseEvent":100,"./SyntheticTouchEvent":101,"./SyntheticUIEvent":102,"./SyntheticWheelEvent":103,"./invariant":134,"./keyOf":141}],93:[function(_dereq_,module,exports){ +},{"./EventConstants":17,"./EventPluginUtils":21,"./EventPropagators":22,"./SyntheticClipboardEvent":96,"./SyntheticDragEvent":98,"./SyntheticEvent":99,"./SyntheticFocusEvent":100,"./SyntheticKeyboardEvent":102,"./SyntheticMouseEvent":103,"./SyntheticTouchEvent":104,"./SyntheticUIEvent":105,"./SyntheticWheelEvent":106,"./getEventCharCode":128,"./invariant":140,"./keyOf":147,"./warning":160}],96:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SyntheticClipboardEvent * @typechecks static-only @@ -16003,21 +16048,14 @@ SyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface); module.exports = SyntheticClipboardEvent; -},{"./SyntheticEvent":96}],94:[function(_dereq_,module,exports){ +},{"./SyntheticEvent":99}],97:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SyntheticCompositionEvent * @typechecks static-only @@ -16056,21 +16094,14 @@ SyntheticEvent.augmentClass( module.exports = SyntheticCompositionEvent; -},{"./SyntheticEvent":96}],95:[function(_dereq_,module,exports){ +},{"./SyntheticEvent":99}],98:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SyntheticDragEvent * @typechecks static-only @@ -16102,21 +16133,14 @@ SyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface); module.exports = SyntheticDragEvent; -},{"./SyntheticMouseEvent":100}],96:[function(_dereq_,module,exports){ +},{"./SyntheticMouseEvent":103}],99:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SyntheticEvent * @typechecks static-only @@ -16126,10 +16150,9 @@ module.exports = SyntheticDragEvent; var PooledClass = _dereq_("./PooledClass"); +var assign = _dereq_("./Object.assign"); var emptyFunction = _dereq_("./emptyFunction"); var getEventTarget = _dereq_("./getEventTarget"); -var merge = _dereq_("./merge"); -var mergeInto = _dereq_("./mergeInto"); /** * @interface Event @@ -16196,7 +16219,7 @@ function SyntheticEvent(dispatchConfig, dispatchMarker, nativeEvent) { this.isPropagationStopped = emptyFunction.thatReturnsFalse; } -mergeInto(SyntheticEvent.prototype, { +assign(SyntheticEvent.prototype, { preventDefault: function() { this.defaultPrevented = true; @@ -16254,11 +16277,11 @@ SyntheticEvent.augmentClass = function(Class, Interface) { var Super = this; var prototype = Object.create(Super.prototype); - mergeInto(prototype, Class.prototype); + assign(prototype, Class.prototype); Class.prototype = prototype; Class.prototype.constructor = Class; - Class.Interface = merge(Super.Interface, Interface); + Class.Interface = assign({}, Super.Interface, Interface); Class.augmentClass = Super.augmentClass; PooledClass.addPoolingTo(Class, PooledClass.threeArgumentPooler); @@ -16268,21 +16291,14 @@ PooledClass.addPoolingTo(SyntheticEvent, PooledClass.threeArgumentPooler); module.exports = SyntheticEvent; -},{"./PooledClass":28,"./emptyFunction":116,"./getEventTarget":125,"./merge":144,"./mergeInto":146}],97:[function(_dereq_,module,exports){ +},{"./Object.assign":29,"./PooledClass":30,"./emptyFunction":121,"./getEventTarget":131}],100:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SyntheticFocusEvent * @typechecks static-only @@ -16314,21 +16330,14 @@ SyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface); module.exports = SyntheticFocusEvent; -},{"./SyntheticUIEvent":102}],98:[function(_dereq_,module,exports){ +},{"./SyntheticUIEvent":105}],101:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SyntheticInputEvent * @typechecks static-only @@ -16368,21 +16377,14 @@ SyntheticEvent.augmentClass( module.exports = SyntheticInputEvent; -},{"./SyntheticEvent":96}],99:[function(_dereq_,module,exports){ +},{"./SyntheticEvent":99}],102:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SyntheticKeyboardEvent * @typechecks static-only @@ -16392,6 +16394,7 @@ module.exports = SyntheticInputEvent; var SyntheticUIEvent = _dereq_("./SyntheticUIEvent"); +var getEventCharCode = _dereq_("./getEventCharCode"); var getEventKey = _dereq_("./getEventKey"); var getEventModifierState = _dereq_("./getEventModifierState"); @@ -16414,11 +16417,10 @@ var KeyboardEventInterface = { // `charCode` is the result of a KeyPress event and represents the value of // the actual printable character. - // KeyPress is deprecated but its replacement is not yet final and not - // implemented in any major browser. + // KeyPress is deprecated, but its replacement is not yet final and not + // implemented in any major browser. Only KeyPress has charCode. if (event.type === 'keypress') { - // IE8 does not implement "charCode", but "keyCode" has the correct value. - return 'charCode' in event ? event.charCode : event.keyCode; + return getEventCharCode(event); } return 0; }, @@ -16437,9 +16439,14 @@ var KeyboardEventInterface = { }, which: function(event) { // `which` is an alias for either `keyCode` or `charCode` depending on the - // type of the event. There is no need to determine the type of the event - // as `keyCode` and `charCode` are either aliased or default to zero. - return event.keyCode || event.charCode; + // type of the event. + if (event.type === 'keypress') { + return getEventCharCode(event); + } + if (event.type === 'keydown' || event.type === 'keyup') { + return event.keyCode; + } + return 0; } }; @@ -16457,21 +16464,14 @@ SyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface); module.exports = SyntheticKeyboardEvent; -},{"./SyntheticUIEvent":102,"./getEventKey":123,"./getEventModifierState":124}],100:[function(_dereq_,module,exports){ +},{"./SyntheticUIEvent":105,"./getEventCharCode":128,"./getEventKey":129,"./getEventModifierState":130}],103:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SyntheticMouseEvent * @typechecks static-only @@ -16547,21 +16547,14 @@ SyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface); module.exports = SyntheticMouseEvent; -},{"./SyntheticUIEvent":102,"./ViewportMetrics":105,"./getEventModifierState":124}],101:[function(_dereq_,module,exports){ +},{"./SyntheticUIEvent":105,"./ViewportMetrics":108,"./getEventModifierState":130}],104:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SyntheticTouchEvent * @typechecks static-only @@ -16602,21 +16595,14 @@ SyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface); module.exports = SyntheticTouchEvent; -},{"./SyntheticUIEvent":102,"./getEventModifierState":124}],102:[function(_dereq_,module,exports){ +},{"./SyntheticUIEvent":105,"./getEventModifierState":130}],105:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SyntheticUIEvent * @typechecks static-only @@ -16671,21 +16657,14 @@ SyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface); module.exports = SyntheticUIEvent; -},{"./SyntheticEvent":96,"./getEventTarget":125}],103:[function(_dereq_,module,exports){ +},{"./SyntheticEvent":99,"./getEventTarget":131}],106:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule SyntheticWheelEvent * @typechecks static-only @@ -16739,21 +16718,14 @@ SyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface); module.exports = SyntheticWheelEvent; -},{"./SyntheticMouseEvent":100}],104:[function(_dereq_,module,exports){ +},{"./SyntheticMouseEvent":103}],107:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule Transaction */ @@ -16985,21 +16957,14 @@ var Transaction = { module.exports = Transaction; -},{"./invariant":134}],105:[function(_dereq_,module,exports){ +},{"./invariant":140}],108:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ViewportMetrics */ @@ -17024,23 +16989,16 @@ var ViewportMetrics = { module.exports = ViewportMetrics; -},{"./getUnboundedScrollPosition":130}],106:[function(_dereq_,module,exports){ +},{"./getUnboundedScrollPosition":136}],109:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * - * @providesModule accumulate + * @providesModule accumulateInto */ "use strict"; @@ -17048,53 +17006,61 @@ module.exports = ViewportMetrics; var invariant = _dereq_("./invariant"); /** - * Accumulates items that must not be null or undefined. * - * This is used to conserve memory by avoiding array allocations. + * Accumulates items that must not be null or undefined into the first one. This + * is used to conserve memory by avoiding array allocations, and thus sacrifices + * API cleanness. Since `current` can be null before being passed in and not + * null after this function, make sure to assign it back to `current`: + * + * `a = accumulateInto(a, b);` + * + * This API should be sparingly used. Try `accumulate` for something cleaner. * * @return {*|array<*>} An accumulation of items. */ -function accumulate(current, next) { + +function accumulateInto(current, next) { ("production" !== "development" ? invariant( next != null, - 'accumulate(...): Accumulated items must be not be null or undefined.' + 'accumulateInto(...): Accumulated items must not be null or undefined.' ) : invariant(next != null)); if (current == null) { return next; - } else { - // Both are not empty. Warning: Never call x.concat(y) when you are not - // certain that x is an Array (x could be a string with concat method). - var currentIsArray = Array.isArray(current); - var nextIsArray = Array.isArray(next); - if (currentIsArray) { - return current.concat(next); - } else { - if (nextIsArray) { - return [current].concat(next); - } else { - return [current, next]; - } - } } + + // Both are not empty. Warning: Never call x.concat(y) when you are not + // certain that x is an Array (x could be a string with concat method). + var currentIsArray = Array.isArray(current); + var nextIsArray = Array.isArray(next); + + if (currentIsArray && nextIsArray) { + current.push.apply(current, next); + return current; + } + + if (currentIsArray) { + current.push(next); + return current; + } + + if (nextIsArray) { + // A bit too dangerous to mutate `next`. + return [current].concat(next); + } + + return [current, next]; } -module.exports = accumulate; +module.exports = accumulateInto; -},{"./invariant":134}],107:[function(_dereq_,module,exports){ +},{"./invariant":140}],110:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule adler32 */ @@ -17107,7 +17073,7 @@ var MOD = 65521; // This is a clean-room implementation of adler32 designed for detecting // if markup is not what we expect it to be. It does not need to be -// cryptographically strong, only reasonable good at detecting if markup +// cryptographically strong, only reasonably good at detecting if markup // generated on the server is different than that on the client. function adler32(data) { var a = 1; @@ -17121,21 +17087,88 @@ function adler32(data) { module.exports = adler32; -},{}],108:[function(_dereq_,module,exports){ +},{}],111:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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 + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * - * http://www.apache.org/licenses/LICENSE-2.0 + * @providesModule camelize + * @typechecks + */ + +var _hyphenPattern = /-(.)/g; + +/** + * Camelcases a hyphenated string, for example: * - * 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. + * > camelize('background-color') + * < "backgroundColor" + * + * @param {string} string + * @return {string} + */ +function camelize(string) { + return string.replace(_hyphenPattern, function(_, character) { + return character.toUpperCase(); + }); +} + +module.exports = camelize; + +},{}],112:[function(_dereq_,module,exports){ +/** + * Copyright 2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule camelizeStyleName + * @typechecks + */ + +"use strict"; + +var camelize = _dereq_("./camelize"); + +var msPattern = /^-ms-/; + +/** + * Camelcases a hyphenated CSS property name, for example: + * + * > camelizeStyleName('background-color') + * < "backgroundColor" + * > camelizeStyleName('-moz-transition') + * < "MozTransition" + * > camelizeStyleName('-ms-transition') + * < "msTransition" + * + * As Andi Smith suggests + * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix + * is converted to lowercase `ms`. + * + * @param {string} string + * @return {string} + */ +function camelizeStyleName(string) { + return camelize(string.replace(msPattern, 'ms-')); +} + +module.exports = camelizeStyleName; + +},{"./camelize":111}],113:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @typechecks * @providesModule cloneWithProps @@ -17143,6 +17176,7 @@ module.exports = adler32; "use strict"; +var ReactElement = _dereq_("./ReactElement"); var ReactPropTransferer = _dereq_("./ReactPropTransferer"); var keyOf = _dereq_("./keyOf"); @@ -17162,7 +17196,7 @@ var CHILDREN_PROP = keyOf({children: null}); function cloneWithProps(child, props) { if ("production" !== "development") { ("production" !== "development" ? warning( - !child.props.ref, + !child.ref, 'You are calling cloneWithProps() on a child with a ref. This is ' + 'dangerous because you\'re creating a new child which will not be ' + 'added as a ref to its parent.' @@ -17178,27 +17212,20 @@ function cloneWithProps(child, props) { } // The current API doesn't retain _owner and _context, which is why this - // doesn't use ReactDescriptor.cloneAndReplaceProps. - return child.constructor(newProps); + // doesn't use ReactElement.cloneAndReplaceProps. + return ReactElement.createElement(child.type, newProps); } module.exports = cloneWithProps; -},{"./ReactPropTransferer":72,"./keyOf":141,"./warning":158}],109:[function(_dereq_,module,exports){ +},{"./ReactElement":58,"./ReactPropTransferer":76,"./keyOf":147,"./warning":160}],114:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule containsNode * @typechecks @@ -17235,77 +17262,14 @@ function containsNode(outerNode, innerNode) { module.exports = containsNode; -},{"./isTextNode":138}],110:[function(_dereq_,module,exports){ +},{"./isTextNode":144}],115:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. - * - * @providesModule copyProperties - */ - -/** - * Copy properties from one or more objects (up to 5) into the first object. - * This is a shallow copy. It mutates the first object and also returns it. - * - * NOTE: `arguments` has a very significant performance penalty, which is why - * we don't support unlimited arguments. - */ -function copyProperties(obj, a, b, c, d, e, f) { - obj = obj || {}; - - if ("production" !== "development") { - if (f) { - throw new Error('Too many arguments passed to copyProperties'); - } - } - - var args = [a, b, c, d, e]; - var ii = 0, v; - while (args[ii]) { - v = args[ii++]; - for (var k in v) { - obj[k] = v[k]; - } - - // IE ignores toString in object iteration.. See: - // webreflection.blogspot.com/2007/07/quick-fix-internet-explorer-and.html - if (v.hasOwnProperty && v.hasOwnProperty('toString') && - (typeof v.toString != 'undefined') && (obj.toString !== v.toString)) { - obj.toString = v.toString; - } - } - - return obj; -} - -module.exports = copyProperties; - -},{}],111:[function(_dereq_,module,exports){ -/** - * Copyright 2013-2014 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule createArrayFrom * @typechecks @@ -17384,21 +17348,14 @@ function createArrayFrom(obj) { module.exports = createArrayFrom; -},{"./toArray":155}],112:[function(_dereq_,module,exports){ +},{"./toArray":157}],116:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule createFullPageComponent * @typechecks @@ -17408,6 +17365,7 @@ module.exports = createArrayFrom; // Defeat circular references by requiring this directly. var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); +var ReactElement = _dereq_("./ReactElement"); var invariant = _dereq_("./invariant"); @@ -17419,14 +17377,14 @@ var invariant = _dereq_("./invariant"); * take advantage of React's reconciliation for styling and <title> * management. So we just document it and throw in dangerous cases. * - * @param {function} componentClass convenience constructor to wrap + * @param {string} tag The tag to wrap * @return {function} convenience constructor of new component */ -function createFullPageComponent(componentClass) { +function createFullPageComponent(tag) { + var elementFactory = ReactElement.createFactory(tag); + var FullPageComponent = ReactCompositeComponent.createClass({ - displayName: 'ReactFullPageComponent' + ( - componentClass.type.displayName || '' - ), + displayName: 'ReactFullPageComponent' + tag, componentWillUnmount: function() { ("production" !== "development" ? invariant( @@ -17440,7 +17398,7 @@ function createFullPageComponent(componentClass) { }, render: function() { - return this.transferPropsTo(componentClass(null, this.props.children)); + return elementFactory(this.props); } }); @@ -17449,21 +17407,14 @@ function createFullPageComponent(componentClass) { module.exports = createFullPageComponent; -},{"./ReactCompositeComponent":38,"./invariant":134}],113:[function(_dereq_,module,exports){ +},{"./ReactCompositeComponent":40,"./ReactElement":58,"./invariant":140}],117:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule createNodesFromMarkup * @typechecks @@ -17544,21 +17495,14 @@ function createNodesFromMarkup(markup, handleScript) { module.exports = createNodesFromMarkup; -},{"./ExecutionEnvironment":22,"./createArrayFrom":111,"./getMarkupWrap":126,"./invariant":134}],114:[function(_dereq_,module,exports){ +},{"./ExecutionEnvironment":23,"./createArrayFrom":115,"./getMarkupWrap":132,"./invariant":140}],118:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule cx */ @@ -17590,21 +17534,14 @@ function cx(classNames) { module.exports = cx; -},{}],115:[function(_dereq_,module,exports){ +},{}],119:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule dangerousStyleValue * @typechecks static-only @@ -17655,27 +17592,67 @@ function dangerousStyleValue(name, value) { module.exports = dangerousStyleValue; -},{"./CSSProperty":4}],116:[function(_dereq_,module,exports){ +},{"./CSSProperty":5}],120:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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 + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * - * http://www.apache.org/licenses/LICENSE-2.0 + * @providesModule deprecated + */ + +var assign = _dereq_("./Object.assign"); +var warning = _dereq_("./warning"); + +/** + * This will log a single deprecation notice per function and forward the call + * on to the new API. * - * 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. + * @param {string} namespace The namespace of the call, eg 'React' + * @param {string} oldName The old function name, eg 'renderComponent' + * @param {string} newName The new function name, eg 'render' + * @param {*} ctx The context this forwarded call should run in + * @param {function} fn The function to forward on to + * @return {*} Will be the value as returned from `fn` + */ +function deprecated(namespace, oldName, newName, ctx, fn) { + var warned = false; + if ("production" !== "development") { + var newFn = function() { + ("production" !== "development" ? warning( + warned, + (namespace + "." + oldName + " will be deprecated in a future version. ") + + ("Use " + namespace + "." + newName + " instead.") + ) : null); + warned = true; + return fn.apply(ctx, arguments); + }; + newFn.displayName = (namespace + "_" + oldName); + // We need to make sure all properties of the original fn are copied over. + // In particular, this is needed to support PropTypes + return assign(newFn, fn); + } + + return fn; +} + +module.exports = deprecated; + +},{"./Object.assign":29,"./warning":160}],121:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule emptyFunction */ -var copyProperties = _dereq_("./copyProperties"); - function makeEmptyFunction(arg) { return function() { return arg; @@ -17689,32 +17666,23 @@ function makeEmptyFunction(arg) { */ function emptyFunction() {} -copyProperties(emptyFunction, { - thatReturns: makeEmptyFunction, - thatReturnsFalse: makeEmptyFunction(false), - thatReturnsTrue: makeEmptyFunction(true), - thatReturnsNull: makeEmptyFunction(null), - thatReturnsThis: function() { return this; }, - thatReturnsArgument: function(arg) { return arg; } -}); +emptyFunction.thatReturns = makeEmptyFunction; +emptyFunction.thatReturnsFalse = makeEmptyFunction(false); +emptyFunction.thatReturnsTrue = makeEmptyFunction(true); +emptyFunction.thatReturnsNull = makeEmptyFunction(null); +emptyFunction.thatReturnsThis = function() { return this; }; +emptyFunction.thatReturnsArgument = function(arg) { return arg; }; module.exports = emptyFunction; -},{"./copyProperties":110}],117:[function(_dereq_,module,exports){ +},{}],122:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule emptyObject */ @@ -17729,21 +17697,14 @@ if ("production" !== "development") { module.exports = emptyObject; -},{}],118:[function(_dereq_,module,exports){ +},{}],123:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule escapeTextForBrowser * @typechecks static-only @@ -17777,27 +17738,22 @@ function escapeTextForBrowser(text) { module.exports = escapeTextForBrowser; -},{}],119:[function(_dereq_,module,exports){ +},{}],124:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule flattenChildren */ "use strict"; +var ReactTextComponent = _dereq_("./ReactTextComponent"); + var traverseAllChildren = _dereq_("./traverseAllChildren"); var warning = _dereq_("./warning"); @@ -17818,7 +17774,18 @@ function flattenSingleChildIntoContext(traverseContext, child, name) { name ) : null); if (keyUnique && child != null) { - result[name] = child; + var type = typeof child; + var normalizedValue; + + if (type === 'string') { + normalizedValue = ReactTextComponent(child); + } else if (type === 'number') { + normalizedValue = ReactTextComponent('' + child); + } else { + normalizedValue = child; + } + + result[name] = normalizedValue; } } @@ -17838,21 +17805,14 @@ function flattenChildren(children) { module.exports = flattenChildren; -},{"./traverseAllChildren":156,"./warning":158}],120:[function(_dereq_,module,exports){ +},{"./ReactTextComponent":87,"./traverseAllChildren":158,"./warning":160}],125:[function(_dereq_,module,exports){ /** - * Copyright 2014 Facebook, Inc. + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule focusNode */ @@ -17860,34 +17820,28 @@ module.exports = flattenChildren; "use strict"; /** - * IE8 throws if an input/textarea is disabled and we try to focus it. - * Focus only when necessary. - * * @param {DOMElement} node input/textarea to focus */ function focusNode(node) { - if (!node.disabled) { + // IE8 can throw "Can't move focus to the control because it is invisible, + // not enabled, or of a type that does not accept the focus." for all kinds of + // reasons that are too expensive and fragile to test. + try { node.focus(); + } catch(e) { } } module.exports = focusNode; -},{}],121:[function(_dereq_,module,exports){ +},{}],126:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule forEachAccumulated */ @@ -17911,21 +17865,14 @@ var forEachAccumulated = function(arr, cb, scope) { module.exports = forEachAccumulated; -},{}],122:[function(_dereq_,module,exports){ +},{}],127:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule getActiveElement * @typechecks @@ -17947,21 +17894,66 @@ function getActiveElement() /*?DOMElement*/ { module.exports = getActiveElement; -},{}],123:[function(_dereq_,module,exports){ +},{}],128:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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 + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * - * http://www.apache.org/licenses/LICENSE-2.0 + * @providesModule getEventCharCode + * @typechecks static-only + */ + +"use strict"; + +/** + * `charCode` represents the actual "character code" and is safe to use with + * `String.fromCharCode`. As such, only keys that correspond to printable + * characters produce a valid `charCode`, the only exception to this is Enter. + * The Tab-key is considered non-printable and does not have a `charCode`, + * presumably because it does not produce a tab-character in browsers. * - * 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. + * @param {object} nativeEvent Native browser event. + * @return {string} Normalized `charCode` property. + */ +function getEventCharCode(nativeEvent) { + var charCode; + var keyCode = nativeEvent.keyCode; + + if ('charCode' in nativeEvent) { + charCode = nativeEvent.charCode; + + // FF does not set `charCode` for the Enter-key, check against `keyCode`. + if (charCode === 0 && keyCode === 13) { + charCode = 13; + } + } else { + // IE8 does not implement `charCode`, but `keyCode` has the correct value. + charCode = keyCode; + } + + // Some non-printable keys are reported in `charCode`/`keyCode`, discard them. + // Must not discard the (non-)printable Enter-key. + if (charCode >= 32 || charCode === 13) { + return charCode; + } + + return 0; +} + +module.exports = getEventCharCode; + +},{}],129:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule getEventKey * @typechecks static-only @@ -17969,7 +17961,7 @@ module.exports = getActiveElement; "use strict"; -var invariant = _dereq_("./invariant"); +var getEventCharCode = _dereq_("./getEventCharCode"); /** * Normalization of deprecated HTML5 `key` values @@ -17991,7 +17983,7 @@ var normalizeKey = { }; /** - * Translation from legacy `which`/`keyCode` to HTML5 `key` + * Translation from legacy `keyCode` to HTML5 `key` * Only special keys supported, all others depend on keyboard layout or browser * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names */ @@ -18043,11 +18035,7 @@ function getEventKey(nativeEvent) { // Browser does not implement `key`, polyfill as much of it as we can. if (nativeEvent.type === 'keypress') { - // Create the character from the `charCode` ourselves and use as an almost - // perfect replacement. - var charCode = 'charCode' in nativeEvent ? - nativeEvent.charCode : - nativeEvent.keyCode; + var charCode = getEventCharCode(nativeEvent); // The enter-key is technically both printable and non-printable and can // thus be captured by `keypress`, no other non-printable key should. @@ -18058,27 +18046,19 @@ function getEventKey(nativeEvent) { // `keyCode` value, almost all function keys have a universal value. return translateToKey[nativeEvent.keyCode] || 'Unidentified'; } - - ("production" !== "development" ? invariant(false, "Unexpected keyboard event type: %s", nativeEvent.type) : invariant(false)); + return ''; } module.exports = getEventKey; -},{"./invariant":134}],124:[function(_dereq_,module,exports){ +},{"./getEventCharCode":128}],130:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule getEventModifierState * @typechecks static-only @@ -18118,21 +18098,14 @@ function getEventModifierState(nativeEvent) { module.exports = getEventModifierState; -},{}],125:[function(_dereq_,module,exports){ +},{}],131:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule getEventTarget * @typechecks static-only @@ -18156,21 +18129,14 @@ function getEventTarget(nativeEvent) { module.exports = getEventTarget; -},{}],126:[function(_dereq_,module,exports){ +},{}],132:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule getMarkupWrap */ @@ -18278,21 +18244,14 @@ function getMarkupWrap(nodeName) { module.exports = getMarkupWrap; -},{"./ExecutionEnvironment":22,"./invariant":134}],127:[function(_dereq_,module,exports){ +},{"./ExecutionEnvironment":23,"./invariant":140}],133:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule getNodeForCharacterOffset */ @@ -18360,21 +18319,14 @@ function getNodeForCharacterOffset(root, offset) { module.exports = getNodeForCharacterOffset; -},{}],128:[function(_dereq_,module,exports){ +},{}],134:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule getReactRootElementInContainer */ @@ -18402,21 +18354,14 @@ function getReactRootElementInContainer(container) { module.exports = getReactRootElementInContainer; -},{}],129:[function(_dereq_,module,exports){ +},{}],135:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule getTextContentAccessor */ @@ -18446,21 +18391,14 @@ function getTextContentAccessor() { module.exports = getTextContentAccessor; -},{"./ExecutionEnvironment":22}],130:[function(_dereq_,module,exports){ +},{"./ExecutionEnvironment":23}],136:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule getUnboundedScrollPosition * @typechecks @@ -18493,21 +18431,14 @@ function getUnboundedScrollPosition(scrollable) { module.exports = getUnboundedScrollPosition; -},{}],131:[function(_dereq_,module,exports){ +},{}],137:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule hyphenate * @typechecks @@ -18533,21 +18464,14 @@ function hyphenate(string) { module.exports = hyphenate; -},{}],132:[function(_dereq_,module,exports){ +},{}],138:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule hyphenateStyleName * @typechecks @@ -18562,11 +18486,11 @@ var msPattern = /^ms-/; /** * Hyphenates a camelcased CSS property name, for example: * - * > hyphenate('backgroundColor') + * > hyphenateStyleName('backgroundColor') * < "background-color" - * > hyphenate('MozTransition') + * > hyphenateStyleName('MozTransition') * < "-moz-transition" - * > hyphenate('msTransition') + * > hyphenateStyleName('msTransition') * < "-ms-transition" * * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix @@ -18581,21 +18505,14 @@ function hyphenateStyleName(string) { module.exports = hyphenateStyleName; -},{"./hyphenate":131}],133:[function(_dereq_,module,exports){ +},{"./hyphenate":137}],139:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule instantiateReactComponent * @typechecks static-only @@ -18603,63 +18520,111 @@ module.exports = hyphenateStyleName; "use strict"; -var invariant = _dereq_("./invariant"); +var warning = _dereq_("./warning"); -/** - * Validate a `componentDescriptor`. This should be exposed publicly in a follow - * up diff. - * - * @param {object} descriptor - * @return {boolean} Returns true if this is a valid descriptor of a Component. - */ -function isValidComponentDescriptor(descriptor) { - return ( - descriptor && - typeof descriptor.type === 'function' && - typeof descriptor.type.prototype.mountComponent === 'function' && - typeof descriptor.type.prototype.receiveComponent === 'function' - ); -} +var ReactElement = _dereq_("./ReactElement"); +var ReactLegacyElement = _dereq_("./ReactLegacyElement"); +var ReactNativeComponent = _dereq_("./ReactNativeComponent"); +var ReactEmptyComponent = _dereq_("./ReactEmptyComponent"); /** - * Given a `componentDescriptor` create an instance that will actually be - * mounted. Currently it just extracts an existing clone from composite - * components but this is an implementation detail which will change. + * Given an `element` create an instance that will actually be mounted. * - * @param {object} descriptor - * @return {object} A new instance of componentDescriptor's constructor. + * @param {object} element + * @param {*} parentCompositeType The composite type that resolved this. + * @return {object} A new instance of the element's constructor. * @protected */ -function instantiateReactComponent(descriptor) { +function instantiateReactComponent(element, parentCompositeType) { + var instance; - // TODO: Make warning - // if (__DEV__) { - ("production" !== "development" ? invariant( - isValidComponentDescriptor(descriptor), - 'Only React Components are valid for mounting.' - ) : invariant(isValidComponentDescriptor(descriptor))); - // } + if ("production" !== "development") { + ("production" !== "development" ? warning( + element && (typeof element.type === 'function' || + typeof element.type === 'string'), + 'Only functions or strings can be mounted as React components.' + ) : null); + + // Resolve mock instances + if (element.type._mockedReactClassConstructor) { + // If this is a mocked class, we treat the legacy factory as if it was the + // class constructor for future proofing unit tests. Because this might + // be mocked as a legacy factory, we ignore any warnings triggerd by + // this temporary hack. + ReactLegacyElement._isLegacyCallWarningEnabled = false; + try { + instance = new element.type._mockedReactClassConstructor( + element.props + ); + } finally { + ReactLegacyElement._isLegacyCallWarningEnabled = true; + } + + // If the mock implementation was a legacy factory, then it returns a + // element. We need to turn this into a real component instance. + if (ReactElement.isValidElement(instance)) { + instance = new instance.type(instance.props); + } + + var render = instance.render; + if (!render) { + // For auto-mocked factories, the prototype isn't shimmed and therefore + // there is no render function on the instance. We replace the whole + // component with an empty component instance instead. + element = ReactEmptyComponent.getEmptyComponent(); + } else { + if (render._isMockFunction && !render._getMockImplementation()) { + // Auto-mocked components may have a prototype with a mocked render + // function. For those, we'll need to mock the result of the render + // since we consider undefined to be invalid results from render. + render.mockImplementation( + ReactEmptyComponent.getEmptyComponent + ); + } + instance.construct(element); + return instance; + } + } + } - return new descriptor.type(descriptor); + // Special case string values + if (typeof element.type === 'string') { + instance = ReactNativeComponent.createInstanceForTag( + element.type, + element.props, + parentCompositeType + ); + } else { + // Normal case for non-mocks and non-strings + instance = new element.type(element.props); + } + + if ("production" !== "development") { + ("production" !== "development" ? warning( + typeof instance.construct === 'function' && + typeof instance.mountComponent === 'function' && + typeof instance.receiveComponent === 'function', + 'Only React Components can be mounted.' + ) : null); + } + + // This actually sets up the internal instance. This will become decoupled + // from the public instance in a future diff. + instance.construct(element); + + return instance; } module.exports = instantiateReactComponent; -},{"./invariant":134}],134:[function(_dereq_,module,exports){ +},{"./ReactElement":58,"./ReactEmptyComponent":60,"./ReactLegacyElement":67,"./ReactNativeComponent":73,"./warning":160}],140:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule invariant */ @@ -18707,21 +18672,14 @@ var invariant = function(condition, format, a, b, c, d, e, f) { module.exports = invariant; -},{}],135:[function(_dereq_,module,exports){ +},{}],141:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule isEventSupported */ @@ -18779,21 +18737,14 @@ function isEventSupported(eventNameSuffix, capture) { module.exports = isEventSupported; -},{"./ExecutionEnvironment":22}],136:[function(_dereq_,module,exports){ +},{"./ExecutionEnvironment":23}],142:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule isNode * @typechecks @@ -18814,21 +18765,14 @@ function isNode(object) { module.exports = isNode; -},{}],137:[function(_dereq_,module,exports){ +},{}],143:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule isTextInputElement */ @@ -18865,21 +18809,14 @@ function isTextInputElement(elem) { module.exports = isTextInputElement; -},{}],138:[function(_dereq_,module,exports){ +},{}],144:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule isTextNode * @typechecks @@ -18897,21 +18834,14 @@ function isTextNode(object) { module.exports = isTextNode; -},{"./isNode":136}],139:[function(_dereq_,module,exports){ +},{"./isNode":142}],145:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule joinClasses * @typechecks static-only @@ -18935,7 +18865,9 @@ function joinClasses(className/*, ... */) { if (argLength > 1) { for (var ii = 1; ii < argLength; ii++) { nextClass = arguments[ii]; - nextClass && (className += ' ' + nextClass); + if (nextClass) { + className = (className ? className + ' ' : '') + nextClass; + } } } return className; @@ -18943,21 +18875,14 @@ function joinClasses(className/*, ... */) { module.exports = joinClasses; -},{}],140:[function(_dereq_,module,exports){ +},{}],146:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule keyMirror * @typechecks static-only @@ -19003,21 +18928,14 @@ var keyMirror = function(obj) { module.exports = keyMirror; -},{"./invariant":134}],141:[function(_dereq_,module,exports){ +},{"./invariant":140}],147:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule keyOf */ @@ -19046,75 +18964,67 @@ var keyOf = function(oneKeyObj) { module.exports = keyOf; -},{}],142:[function(_dereq_,module,exports){ +},{}],148:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule mapObject */ -"use strict"; +'use strict'; + +var hasOwnProperty = Object.prototype.hasOwnProperty; /** - * For each key/value pair, invokes callback func and constructs a resulting - * object which contains, for every key in obj, values that are the result of - * of invoking the function: + * Executes the provided `callback` once for each enumerable own property in the + * object and constructs a new object from the results. The `callback` is + * invoked with three arguments: * - * func(value, key, iteration) + * - the property value + * - the property name + * - the object being traversed * - * Grepable names: + * Properties that are added after the call to `mapObject` will not be visited + * by `callback`. If the values of existing properties are changed, the value + * passed to `callback` will be the value at the time `mapObject` visits them. + * Properties that are deleted before being visited are not visited. * - * function objectMap() - * function objMap() + * @grep function objectMap() + * @grep function objMap() * - * @param {?object} obj Object to map keys over - * @param {function} func Invoked for each key/val pair. - * @param {?*} context - * @return {?object} Result of mapping or null if obj is falsey + * @param {?object} object + * @param {function} callback + * @param {*} context + * @return {?object} */ -function mapObject(obj, func, context) { - if (!obj) { +function mapObject(object, callback, context) { + if (!object) { return null; } - var i = 0; - var ret = {}; - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - ret[key] = func.call(context, obj[key], key, i++); + var result = {}; + for (var name in object) { + if (hasOwnProperty.call(object, name)) { + result[name] = callback.call(context, object[name], name, object); } } - return ret; + return result; } module.exports = mapObject; -},{}],143:[function(_dereq_,module,exports){ +},{}],149:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule memoizeStringOnly * @typechecks static-only @@ -19141,293 +19051,14 @@ function memoizeStringOnly(callback) { module.exports = memoizeStringOnly; -},{}],144:[function(_dereq_,module,exports){ -/** - * Copyright 2013-2014 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. - * - * @providesModule merge - */ - -"use strict"; - -var mergeInto = _dereq_("./mergeInto"); - -/** - * Shallow merges two structures into a return value, without mutating either. - * - * @param {?object} one Optional object with properties to merge from. - * @param {?object} two Optional object with properties to merge from. - * @return {object} The shallow extension of one by two. - */ -var merge = function(one, two) { - var result = {}; - mergeInto(result, one); - mergeInto(result, two); - return result; -}; - -module.exports = merge; - -},{"./mergeInto":146}],145:[function(_dereq_,module,exports){ -/** - * Copyright 2013-2014 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. - * - * @providesModule mergeHelpers - * - * requiresPolyfills: Array.isArray - */ - -"use strict"; - -var invariant = _dereq_("./invariant"); -var keyMirror = _dereq_("./keyMirror"); - +},{}],150:[function(_dereq_,module,exports){ /** - * Maximum number of levels to traverse. Will catch circular structures. - * @const - */ -var MAX_MERGE_DEPTH = 36; - -/** - * We won't worry about edge cases like new String('x') or new Boolean(true). - * Functions are considered terminals, and arrays are not. - * @param {*} o The item/object/value to test. - * @return {boolean} true iff the argument is a terminal. - */ -var isTerminal = function(o) { - return typeof o !== 'object' || o === null; -}; - -var mergeHelpers = { - - MAX_MERGE_DEPTH: MAX_MERGE_DEPTH, - - isTerminal: isTerminal, - - /** - * Converts null/undefined values into empty object. - * - * @param {?Object=} arg Argument to be normalized (nullable optional) - * @return {!Object} - */ - normalizeMergeArg: function(arg) { - return arg === undefined || arg === null ? {} : arg; - }, - - /** - * If merging Arrays, a merge strategy *must* be supplied. If not, it is - * likely the caller's fault. If this function is ever called with anything - * but `one` and `two` being `Array`s, it is the fault of the merge utilities. - * - * @param {*} one Array to merge into. - * @param {*} two Array to merge from. - */ - checkMergeArrayArgs: function(one, two) { - ("production" !== "development" ? invariant( - Array.isArray(one) && Array.isArray(two), - 'Tried to merge arrays, instead got %s and %s.', - one, - two - ) : invariant(Array.isArray(one) && Array.isArray(two))); - }, - - /** - * @param {*} one Object to merge into. - * @param {*} two Object to merge from. - */ - checkMergeObjectArgs: function(one, two) { - mergeHelpers.checkMergeObjectArg(one); - mergeHelpers.checkMergeObjectArg(two); - }, - - /** - * @param {*} arg - */ - checkMergeObjectArg: function(arg) { - ("production" !== "development" ? invariant( - !isTerminal(arg) && !Array.isArray(arg), - 'Tried to merge an object, instead got %s.', - arg - ) : invariant(!isTerminal(arg) && !Array.isArray(arg))); - }, - - /** - * @param {*} arg - */ - checkMergeIntoObjectArg: function(arg) { - ("production" !== "development" ? invariant( - (!isTerminal(arg) || typeof arg === 'function') && !Array.isArray(arg), - 'Tried to merge into an object, instead got %s.', - arg - ) : invariant((!isTerminal(arg) || typeof arg === 'function') && !Array.isArray(arg))); - }, - - /** - * Checks that a merge was not given a circular object or an object that had - * too great of depth. - * - * @param {number} Level of recursion to validate against maximum. - */ - checkMergeLevel: function(level) { - ("production" !== "development" ? invariant( - level < MAX_MERGE_DEPTH, - 'Maximum deep merge depth exceeded. You may be attempting to merge ' + - 'circular structures in an unsupported way.' - ) : invariant(level < MAX_MERGE_DEPTH)); - }, - - /** - * Checks that the supplied merge strategy is valid. - * - * @param {string} Array merge strategy. - */ - checkArrayStrategy: function(strategy) { - ("production" !== "development" ? invariant( - strategy === undefined || strategy in mergeHelpers.ArrayStrategies, - 'You must provide an array strategy to deep merge functions to ' + - 'instruct the deep merge how to resolve merging two arrays.' - ) : invariant(strategy === undefined || strategy in mergeHelpers.ArrayStrategies)); - }, - - /** - * Set of possible behaviors of merge algorithms when encountering two Arrays - * that must be merged together. - * - `clobber`: The left `Array` is ignored. - * - `indexByIndex`: The result is achieved by recursively deep merging at - * each index. (not yet supported.) - */ - ArrayStrategies: keyMirror({ - Clobber: true, - IndexByIndex: true - }) - -}; - -module.exports = mergeHelpers; - -},{"./invariant":134,"./keyMirror":140}],146:[function(_dereq_,module,exports){ -/** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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. - * - * @providesModule mergeInto - * @typechecks static-only - */ - -"use strict"; - -var mergeHelpers = _dereq_("./mergeHelpers"); - -var checkMergeObjectArg = mergeHelpers.checkMergeObjectArg; -var checkMergeIntoObjectArg = mergeHelpers.checkMergeIntoObjectArg; - -/** - * Shallow merges two structures by mutating the first parameter. - * - * @param {object|function} one Object to be merged into. - * @param {?object} two Optional object with properties to merge from. - */ -function mergeInto(one, two) { - checkMergeIntoObjectArg(one); - if (two != null) { - checkMergeObjectArg(two); - for (var key in two) { - if (!two.hasOwnProperty(key)) { - continue; - } - one[key] = two[key]; - } - } -} - -module.exports = mergeInto; - -},{"./mergeHelpers":145}],147:[function(_dereq_,module,exports){ -/** - * Copyright 2013-2014 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. - * - * @providesModule mixInto - */ - -"use strict"; - -/** - * Simply copies properties to the prototype. - */ -var mixInto = function(constructor, methodBag) { - var methodName; - for (methodName in methodBag) { - if (!methodBag.hasOwnProperty(methodName)) { - continue; - } - constructor.prototype[methodName] = methodBag[methodName]; - } -}; - -module.exports = mixInto; - -},{}],148:[function(_dereq_,module,exports){ -/** - * Copyright 2014 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule monitorCodeUse */ @@ -19452,27 +19083,20 @@ function monitorCodeUse(eventName, data) { module.exports = monitorCodeUse; -},{"./invariant":134}],149:[function(_dereq_,module,exports){ +},{"./invariant":140}],151:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule onlyChild */ "use strict"; -var ReactDescriptor = _dereq_("./ReactDescriptor"); +var ReactElement = _dereq_("./ReactElement"); var invariant = _dereq_("./invariant"); @@ -19489,29 +19113,22 @@ var invariant = _dereq_("./invariant"); */ function onlyChild(children) { ("production" !== "development" ? invariant( - ReactDescriptor.isValidDescriptor(children), + ReactElement.isValidElement(children), 'onlyChild must be passed a children with exactly one child.' - ) : invariant(ReactDescriptor.isValidDescriptor(children))); + ) : invariant(ReactElement.isValidElement(children))); return children; } module.exports = onlyChild; -},{"./ReactDescriptor":56,"./invariant":134}],150:[function(_dereq_,module,exports){ +},{"./ReactElement":58,"./invariant":140}],152:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule performance * @typechecks @@ -19532,21 +19149,14 @@ if (ExecutionEnvironment.canUseDOM) { module.exports = performance || {}; -},{"./ExecutionEnvironment":22}],151:[function(_dereq_,module,exports){ +},{"./ExecutionEnvironment":23}],153:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule performanceNow * @typechecks @@ -19567,21 +19177,14 @@ var performanceNow = performance.now.bind(performance); module.exports = performanceNow; -},{"./performance":150}],152:[function(_dereq_,module,exports){ +},{"./performance":152}],154:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule setInnerHTML */ @@ -19590,6 +19193,9 @@ module.exports = performanceNow; var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); +var WHITESPACE_TEST = /^[ \r\n\t\f]/; +var NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/; + /** * Set the innerHTML property of a node, ensuring that whitespace is preserved * even in IE8. @@ -19626,13 +19232,8 @@ if (ExecutionEnvironment.canUseDOM) { // thin air on IE8, this only happens if there is no visible text // in-front of the non-visible tags. Piggyback on the whitespace fix // and simply check if any non-visible tags appear in the source. - if (html.match(/^[ \r\n\t\f]/) || - html[0] === '<' && ( - html.indexOf('<noscript') !== -1 || - html.indexOf('<script') !== -1 || - html.indexOf('<style') !== -1 || - html.indexOf('<meta') !== -1 || - html.indexOf('<link') !== -1)) { + if (WHITESPACE_TEST.test(html) || + html[0] === '<' && NONVISIBLE_TEST.test(html)) { // Recover leading whitespace by temporarily prepending any character. // \uFEFF has the potential advantage of being zero-width/invisible. node.innerHTML = '\uFEFF' + html; @@ -19654,21 +19255,14 @@ if (ExecutionEnvironment.canUseDOM) { module.exports = setInnerHTML; -},{"./ExecutionEnvironment":22}],153:[function(_dereq_,module,exports){ +},{"./ExecutionEnvironment":23}],155:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule shallowEqual */ @@ -19694,7 +19288,7 @@ function shallowEqual(objA, objB) { return false; } } - // Test for B'a keys missing from A. + // Test for B's keys missing from A. for (key in objB) { if (objB.hasOwnProperty(key) && !objA.hasOwnProperty(key)) { return false; @@ -19705,21 +19299,14 @@ function shallowEqual(objA, objB) { module.exports = shallowEqual; -},{}],154:[function(_dereq_,module,exports){ +},{}],156:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 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 + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule shouldUpdateReactComponent * @typechecks static-only @@ -19728,22 +19315,21 @@ module.exports = shallowEqual; "use strict"; /** - * Given a `prevDescriptor` and `nextDescriptor`, determines if the existing + * Given a `prevElement` and `nextElement`, determines if the existing * instance should be updated as opposed to being destroyed or replaced by a new - * instance. Both arguments are descriptors. This ensures that this logic can + * instance. Both arguments are elements. This ensures that this logic can * operate on stateless trees without any backing instance. * - * @param {?object} prevDescriptor - * @param {?object} nextDescriptor + * @param {?object} prevElement + * @param {?object} nextElement * @return {boolean} True if the existing instance should be updated. * @protected */ -function shouldUpdateReactComponent(prevDescriptor, nextDescriptor) { - if (prevDescriptor && nextDescriptor && - prevDescriptor.type === nextDescriptor.type && ( - (prevDescriptor.props && prevDescriptor.props.key) === - (nextDescriptor.props && nextDescriptor.props.key) - ) && prevDescriptor._owner === nextDescriptor._owner) { +function shouldUpdateReactComponent(prevElement, nextElement) { + if (prevElement && nextElement && + prevElement.type === nextElement.type && + prevElement.key === nextElement.key && + prevElement._owner === nextElement._owner) { return true; } return false; @@ -19751,21 +19337,14 @@ function shouldUpdateReactComponent(prevDescriptor, nextDescriptor) { module.exports = shouldUpdateReactComponent; -},{}],155:[function(_dereq_,module,exports){ +},{}],157:[function(_dereq_,module,exports){ /** - * Copyright 2014 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 + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule toArray * @typechecks @@ -19828,29 +19407,22 @@ function toArray(obj) { module.exports = toArray; -},{"./invariant":134}],156:[function(_dereq_,module,exports){ +},{"./invariant":140}],158:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule traverseAllChildren */ "use strict"; +var ReactElement = _dereq_("./ReactElement"); var ReactInstanceHandles = _dereq_("./ReactInstanceHandles"); -var ReactTextComponent = _dereq_("./ReactTextComponent"); var invariant = _dereq_("./invariant"); @@ -19885,9 +19457,9 @@ function userProvidedKeyEscaper(match) { * @return {string} */ function getComponentKey(component, index) { - if (component && component.props && component.props.key != null) { + if (component && component.key != null) { // Explicit key - return wrapUserProvidedKey(component.props.key); + return wrapUserProvidedKey(component.key); } // Implicit key determined by the index in the set return index.toString(36); @@ -19928,16 +19500,17 @@ function wrapUserProvidedKey(key) { */ var traverseAllChildrenImpl = function(children, nameSoFar, indexSoFar, callback, traverseContext) { + var nextName, nextIndex; var subtreeCount = 0; // Count of children found in the current subtree. if (Array.isArray(children)) { for (var i = 0; i < children.length; i++) { var child = children[i]; - var nextName = ( + nextName = ( nameSoFar + (nameSoFar ? SUBSEPARATOR : SEPARATOR) + getComponentKey(child, i) ); - var nextIndex = indexSoFar + subtreeCount; + nextIndex = indexSoFar + subtreeCount; subtreeCount += traverseAllChildrenImpl( child, nextName, @@ -19957,40 +19530,32 @@ var traverseAllChildrenImpl = // All of the above are perceived as null. callback(traverseContext, null, storageName, indexSoFar); subtreeCount = 1; - } else if (children.type && children.type.prototype && - children.type.prototype.mountComponentIntoNode) { + } else if (type === 'string' || type === 'number' || + ReactElement.isValidElement(children)) { callback(traverseContext, children, storageName, indexSoFar); subtreeCount = 1; - } else { - if (type === 'object') { - ("production" !== "development" ? invariant( - !children || children.nodeType !== 1, - 'traverseAllChildren(...): Encountered an invalid child; DOM ' + - 'elements are not valid children of React components.' - ) : invariant(!children || children.nodeType !== 1)); - for (var key in children) { - if (children.hasOwnProperty(key)) { - subtreeCount += traverseAllChildrenImpl( - children[key], - ( - nameSoFar + (nameSoFar ? SUBSEPARATOR : SEPARATOR) + - wrapUserProvidedKey(key) + SUBSEPARATOR + - getComponentKey(children[key], 0) - ), - indexSoFar + subtreeCount, - callback, - traverseContext - ); - } + } else if (type === 'object') { + ("production" !== "development" ? invariant( + !children || children.nodeType !== 1, + 'traverseAllChildren(...): Encountered an invalid child; DOM ' + + 'elements are not valid children of React components.' + ) : invariant(!children || children.nodeType !== 1)); + for (var key in children) { + if (children.hasOwnProperty(key)) { + nextName = ( + nameSoFar + (nameSoFar ? SUBSEPARATOR : SEPARATOR) + + wrapUserProvidedKey(key) + SUBSEPARATOR + + getComponentKey(children[key], 0) + ); + nextIndex = indexSoFar + subtreeCount; + subtreeCount += traverseAllChildrenImpl( + children[key], + nextName, + nextIndex, + callback, + traverseContext + ); } - } else if (type === 'string') { - var normalizedText = ReactTextComponent(children); - callback(traverseContext, normalizedText, storageName, indexSoFar); - subtreeCount += 1; - } else if (type === 'number') { - var normalizedNumber = ReactTextComponent('' + children); - callback(traverseContext, normalizedNumber, storageName, indexSoFar); - subtreeCount += 1; } } } @@ -20023,28 +19588,21 @@ function traverseAllChildren(children, callback, traverseContext) { module.exports = traverseAllChildren; -},{"./ReactInstanceHandles":64,"./ReactTextComponent":83,"./invariant":134}],157:[function(_dereq_,module,exports){ +},{"./ReactElement":58,"./ReactInstanceHandles":66,"./invariant":140}],159:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014 Facebook, Inc. + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule update */ "use strict"; -var copyProperties = _dereq_("./copyProperties"); +var assign = _dereq_("./Object.assign"); var keyOf = _dereq_("./keyOf"); var invariant = _dereq_("./invariant"); @@ -20052,7 +19610,7 @@ function shallowCopy(x) { if (Array.isArray(x)) { return x.concat(); } else if (x && typeof x === 'object') { - return copyProperties(new x.constructor(), x); + return assign(new x.constructor(), x); } else { return x; } @@ -20132,7 +19690,7 @@ function update(value, spec) { COMMAND_MERGE, nextValue ) : invariant(nextValue && typeof nextValue === 'object')); - copyProperties(nextValue, spec[COMMAND_MERGE]); + assign(nextValue, spec[COMMAND_MERGE]); } if (spec.hasOwnProperty(COMMAND_PUSH)) { @@ -20196,21 +19754,14 @@ function update(value, spec) { module.exports = update; -},{"./copyProperties":110,"./invariant":134,"./keyOf":141}],158:[function(_dereq_,module,exports){ +},{"./Object.assign":29,"./invariant":140,"./keyOf":147}],160:[function(_dereq_,module,exports){ /** - * Copyright 2014 Facebook, Inc. + * Copyright 2014, Facebook, Inc. + * All rights reserved. * - * 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. + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule warning */ @@ -20229,7 +19780,7 @@ var emptyFunction = _dereq_("./emptyFunction"); var warning = emptyFunction; if ("production" !== "development") { - warning = function(condition, format ) {var args=Array.prototype.slice.call(arguments,2); + warning = function(condition, format ) {for (var args=[],$__0=2,$__1=arguments.length;$__0<$__1;$__0++) args.push(arguments[$__0]); if (format === undefined) { throw new Error( '`warning(condition, format, ...args)` requires a warning ' + @@ -20246,6 +19797,5 @@ if ("production" !== "development") { module.exports = warning; -},{"./emptyFunction":116}]},{},[88]) -(88) +},{"./emptyFunction":121}]},{},[1])(1) });
\ No newline at end of file |