From f0880a223c57e76095e4a2575bb9de86160dd1a8 Mon Sep 17 00:00:00 2001 From: andersea Date: Mon, 6 Apr 2015 12:31:04 +0200 Subject: [PATCH 001/755] Disable caching of Comments() action Adds an OutputCache attribute the the Comments() action, to prevent IE from aggressively caching the comments list. Otherwise IE will only show the comments that were returned in the first request unless you refresh the entire page. --- site/jekyll/getting-started/tutorial.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/site/jekyll/getting-started/tutorial.md b/site/jekyll/getting-started/tutorial.md index db9a31956..04f5f791c 100644 --- a/site/jekyll/getting-started/tutorial.md +++ b/site/jekyll/getting-started/tutorial.md @@ -402,13 +402,16 @@ namespace ReactDemo.Controllers Let's also add a new controller action to return the list of comments: ```csharp +[OutputCache(Location = OutputCacheLocation.None)] public ActionResult Comments() { return Json(_comments, JsonRequestBehavior.AllowGet); } ``` -And a corresponding route in `App_Start\RouteConfig.cs`: +The `OutputCache` attribute is used here to prevent IE from caching the ajax request. IE tries to optimize things by assuming that identical requests will return identical responses. Subsequent calls to the Comments action will simply return the cached response from the first call, the result being that the comment list is never updated in IE as new comments are added. When designing a real world API, cache times of API requests should be considered more carefully. For this tutorial it is easiest to simply disable caching. + +Finally we add a corresponding route in `App_Start\RouteConfig.cs` to simplify the request URL a bit: ```csharp{12-16} using System.Web.Mvc; From 0552613ae4c03ad1643eef9d9e20c8e921c89e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Fri, 10 Apr 2015 12:15:34 -0700 Subject: [PATCH 002/755] Update Patent Grant https://code.facebook.com/posts/1639473982937255/updating-our-open-source-patent-grant/ --- PATENTS | 48 +++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/PATENTS b/PATENTS index e0ee8eb12..755baf53f 100644 --- a/PATENTS +++ b/PATENTS @@ -1,23 +1,33 @@ -Additional Grant of Patent Rights +Additional Grant of Patent Rights Version 2 -�Software� means the ReactJS.NET software distributed by Facebook, Inc. +"Software" means the ReactJS.NET software distributed by Facebook, Inc. -Facebook hereby grants you a perpetual, worldwide, royalty-free, non-exclusive, -irrevocable (subject to the termination provision below) license under any -rights in any patent claims owned by Facebook, to make, have made, use, sell, -offer to sell, import, and otherwise transfer the Software. For avoidance of -doubt, no license is granted under Facebook�s rights in any patent claims that -are infringed by (i) modifications to the Software made by you or a third party, -or (ii) the Software in combination with any software or other technology -provided by you or a third party. +Facebook, Inc. ("Facebook") hereby grants to each recipient of the Software +("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable +(subject to the termination provision below) license under any Necessary +Claims, to make, have made, use, sell, offer to sell, import, and otherwise +transfer the Software. For avoidance of doubt, no license is granted under +Facebook's rights in any patent claims that are infringed by (i) modifications +to the Software made by you or any third party or (ii) the Software in +combination with any software or other technology. The license granted hereunder will terminate, automatically and without notice, -for anyone that makes any claim (including by filing any lawsuit, assertion or -other action) alleging (a) direct, indirect, or contributory infringement or -inducement to infringe any patent: (i) by Facebook or any of its subsidiaries or -affiliates, whether or not such claim is related to the Software, (ii) by any -party if such claim arises in whole or in part from any software, product or -service of Facebook or any of its subsidiaries or affiliates, whether or not -such claim is related to the Software, or (iii) by any party relating to the -Software; or (b) that any right in any patent claim of Facebook is invalid or -unenforceable. \ No newline at end of file +if you (or any of your subsidiaries, corporate affiliates or agents) initiate +directly or indirectly, or take a direct financial interest in, any Patent +Assertion: (i) against Facebook or any of its subsidiaries or corporate +affiliates, (ii) against any party if such Patent Assertion arises in whole or +in part from any software, technology, product or service of Facebook or any of +its subsidiaries or corporate affiliates, or (iii) against any party relating +to the Software. Notwithstanding the foregoing, if Facebook or any of its +subsidiaries or corporate affiliates files a lawsuit alleging patent +infringement against you in the first instance, and you respond by filing a +patent infringement counterclaim in that lawsuit against that party that is +unrelated to the Software, the license granted hereunder will not terminate +under section (i) of this paragraph due to such counterclaim. + +A "Necessary Claim" is a claim of a patent owned by Facebook that is +necessarily infringed by the Software standing alone. + +A "Patent Assertion" is any lawsuit or other action alleging direct, indirect, +or contributory infringement or inducement to infringe any patent, including a +cross-claim or counterclaim. From 5b5a51297f80a46357d62dc7e4be1f7a73181c1b Mon Sep 17 00:00:00 2001 From: Daniel Lo Nigro Date: Sat, 11 Apr 2015 16:02:53 -0700 Subject: [PATCH 003/755] Add JavaScriptEngineSwitcher references to avoid issues with older MSBuild MSBuild 12.0 and below have started throwing errors like "The type 'JavaScriptEngineSwitcher.Core.IJsEngine' is defined in an assembly that is not referenced. You must add a reference to assembly 'JavaScriptEngineSwitcher.Core, Version=1.2.4.0, Culture=neutral, PublicKeyToken=c608b2a8cc9e4472'" with the build. Referencing JavaScriptEngineSwitcher in more assemblies was enough to make it happy. Strangely, MSBuild 14.0 was fine before this change. --- src/React.AspNet/project.json | 5 +++-- src/React.Owin/React.Owin.csproj | 4 ++++ src/React.Owin/packages.config | 1 + src/React.Sample.Cassette/React.Sample.Cassette.csproj | 3 +++ src/React.Sample.Cassette/packages.config | 1 + src/React.Web/React.Web.csproj | 4 ++++ src/React.Web/packages.config | 1 + 7 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/React.AspNet/project.json b/src/React.AspNet/project.json index 47f0b7bef..3107ec59f 100644 --- a/src/React.AspNet/project.json +++ b/src/React.AspNet/project.json @@ -10,7 +10,7 @@ "compilationOptions": { "define": [ "RELEASE", "TRACE", "ASPNET5" ], "optimize": true, - "warningsAsErrors": true, + "warningsAsErrors": true } } }, @@ -19,7 +19,8 @@ "Microsoft.AspNet.Hosting": "1.0.0.0-beta3", "Microsoft.AspNet.Mvc.Core": "6.0.0.0-beta3", "Microsoft.AspNet.StaticFiles": "1.0.0.0-beta3", - "React.Core": "" + "React.Core": "", + "JavaScriptEngineSwitcher.Core": "1.2.4.0" }, "frameworks": { "aspnet50": { } diff --git a/src/React.Owin/React.Owin.csproj b/src/React.Owin/React.Owin.csproj index b53be0c33..cf715d658 100644 --- a/src/React.Owin/React.Owin.csproj +++ b/src/React.Owin/React.Owin.csproj @@ -44,6 +44,10 @@ true + + False + ..\packages\JavaScriptEngineSwitcher.Core.1.2.4\lib\net40\JavaScriptEngineSwitcher.Core.dll + False ..\packages\Microsoft.Owin.3.0.0\lib\net45\Microsoft.Owin.dll diff --git a/src/React.Owin/packages.config b/src/React.Owin/packages.config index 8e9cc26ec..204e1c1d4 100644 --- a/src/React.Owin/packages.config +++ b/src/React.Owin/packages.config @@ -1,5 +1,6 @@  + diff --git a/src/React.Sample.Cassette/React.Sample.Cassette.csproj b/src/React.Sample.Cassette/React.Sample.Cassette.csproj index d6a71b343..bd29e8635 100644 --- a/src/React.Sample.Cassette/React.Sample.Cassette.csproj +++ b/src/React.Sample.Cassette/React.Sample.Cassette.csproj @@ -66,6 +66,9 @@ False ..\packages\Cassette.Views.2.4.1\lib\net40\Cassette.Views.dll + + ..\packages\JavaScriptEngineSwitcher.Core.1.2.4\lib\net40\JavaScriptEngineSwitcher.Core.dll + diff --git a/src/React.Sample.Cassette/packages.config b/src/React.Sample.Cassette/packages.config index 3b041ee28..2e9346e8b 100644 --- a/src/React.Sample.Cassette/packages.config +++ b/src/React.Sample.Cassette/packages.config @@ -5,6 +5,7 @@ + diff --git a/src/React.Web/React.Web.csproj b/src/React.Web/React.Web.csproj index 0e6d7665a..0f42f6848 100644 --- a/src/React.Web/React.Web.csproj +++ b/src/React.Web/React.Web.csproj @@ -42,6 +42,10 @@ ..\Key.snk + + False + ..\packages\JavaScriptEngineSwitcher.Core.1.2.4\lib\net40\JavaScriptEngineSwitcher.Core.dll + True ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll diff --git a/src/React.Web/packages.config b/src/React.Web/packages.config index 821191594..f62138e42 100644 --- a/src/React.Web/packages.config +++ b/src/React.Web/packages.config @@ -1,5 +1,6 @@  + From 6f26ae9688d1ab3a54467cda2ee84f2db743303b Mon Sep 17 00:00:00 2001 From: Daniel Lo Nigro Date: Sat, 11 Apr 2015 17:10:35 -0700 Subject: [PATCH 004/755] Add option to blacklist MSIE engine. --- src/React.Core/IReactSiteConfiguration.cs | 10 ++++++++++ src/React.Core/JavaScriptEngineFactory.cs | 22 ++++++++++++++++++---- src/React.Core/ReactSiteConfiguration.cs | 16 ++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/React.Core/IReactSiteConfiguration.cs b/src/React.Core/IReactSiteConfiguration.cs index ed90ebca8..a240824ef 100644 --- a/src/React.Core/IReactSiteConfiguration.cs +++ b/src/React.Core/IReactSiteConfiguration.cs @@ -99,5 +99,15 @@ public interface IReactSiteConfiguration /// Defaults to 25. /// IReactSiteConfiguration SetMaxEngines(int? maxEngines); + + /// + /// Gets or sets whether the MSIE engine should be used if V8 is unavailable. + /// + bool AllowMsieEngine { get; set; } + /// + /// Sets whether the MSIE engine should be used if V8 is unavailable. + /// + /// + IReactSiteConfiguration SetAllowMsieEngine(bool allowMsieEngine); } } diff --git a/src/React.Core/JavaScriptEngineFactory.cs b/src/React.Core/JavaScriptEngineFactory.cs index 0b2755303..77d920ace 100644 --- a/src/React.Core/JavaScriptEngineFactory.cs +++ b/src/React.Core/JavaScriptEngineFactory.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using JavaScriptEngineSwitcher.Core; +using JavaScriptEngineSwitcher.Msie; using JavaScriptEngineSwitcher.V8; using JSPool; using React.Exceptions; @@ -72,7 +73,7 @@ IFileSystem fileSystem { _config = config; _fileSystem = fileSystem; - _factory = GetFactory(availableFactories); + _factory = GetFactory(availableFactories, config.AllowMsieEngine); if (_config.ReuseJavaScriptEngines) { _pool = CreatePool(); @@ -197,7 +198,7 @@ public virtual void ReturnEngineToPool(IJsEngine engine) /// The first functioning JavaScript engine with the lowest priority will be used. /// /// Function to create JavaScript engine - private static Func GetFactory(IEnumerable availableFactories) + private static Func GetFactory(IEnumerable availableFactories, bool allowMsie) { var availableEngineFactories = availableFactories .OrderBy(x => x.Priority) @@ -208,8 +209,7 @@ private static Func GetFactory(IEnumerable availableFac try { engine = engineFactory(); - // Perform a sanity test to ensure this engine is usable - if (engine.Evaluate("1 + 1") == 2) + if (EngineIsUsable(engine, allowMsie)) { // Success! Use this one. return engineFactory; @@ -246,6 +246,20 @@ private static Func GetFactory(IEnumerable availableFac throw new ReactEngineNotFoundException(); } + /// + /// Performs a sanity check to ensure the specified engine type is usable. + /// + /// Engine to test + /// Whether the MSIE engine can be used + /// + private static bool EngineIsUsable(IJsEngine engine, bool allowMsie) + { + // Perform a sanity test to ensure this engine is usable + var isUsable = engine.Evaluate("1 + 1") == 2; + var isMsie = engine is MsieJsEngine; + return isUsable && (!isMsie || allowMsie); + } + /// /// Clean up all engines /// diff --git a/src/React.Core/ReactSiteConfiguration.cs b/src/React.Core/ReactSiteConfiguration.cs index 84a219a37..e9a525415 100644 --- a/src/React.Core/ReactSiteConfiguration.cs +++ b/src/React.Core/ReactSiteConfiguration.cs @@ -35,6 +35,7 @@ public ReactSiteConfiguration() { UseHarmony = true; ReuseJavaScriptEngines = true; + AllowMsieEngine = true; } /// @@ -154,5 +155,20 @@ public IReactSiteConfiguration SetMaxEngines(int? maxEngines) MaxEngines = maxEngines; return this; } + + /// + /// Gets or sets whether the MSIE engine should be used if V8 is unavailable. + /// + public bool AllowMsieEngine { get; set; } + + /// + /// Sets whether the MSIE engine should be used if V8 is unavailable. + /// + /// + public IReactSiteConfiguration SetAllowMsieEngine(bool allowMsieEngine) + { + AllowMsieEngine = allowMsieEngine; + return this; + } } } From c002df3c8f797fb3b3ffd18734e4e5238b50ea85 Mon Sep 17 00:00:00 2001 From: Daniel Lo Nigro Date: Sat, 11 Apr 2015 17:15:05 -0700 Subject: [PATCH 005/755] Include InnerException when ClearScript can't be initialised --- .../Exceptions/ClearScriptV8InitialisationException.cs | 8 ++++---- src/React.Core/JavaScriptEngineFactory.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/React.Core/Exceptions/ClearScriptV8InitialisationException.cs b/src/React.Core/Exceptions/ClearScriptV8InitialisationException.cs index 222ba7109..bd077e2b9 100644 --- a/src/React.Core/Exceptions/ClearScriptV8InitialisationException.cs +++ b/src/React.Core/Exceptions/ClearScriptV8InitialisationException.cs @@ -21,8 +21,8 @@ public class ClearScriptV8InitialisationException : ReactException /// /// Initializes a new instance of the class. /// - public ClearScriptV8InitialisationException(string innerMessage) : - base(GetMessage(innerMessage)) { } + public ClearScriptV8InitialisationException(Exception innerException) : + base(GetMessage(innerException), innerException) { } /// /// Used by deserialization @@ -33,7 +33,7 @@ protected ClearScriptV8InitialisationException(SerializationInfo info, Streaming /// /// Gets a message that describes the current exception. /// - private static string GetMessage(string innerMessage) + private static string GetMessage(Exception innerException) { return "Failed to initialise ClearScript V8. This is most likely caused by the native libraries " + @@ -41,7 +41,7 @@ private static string GetMessage(string innerMessage) "Visual C++ runtime not being installed. Please ensure your app is referencing the " + "JavaScriptEngineSwitcher.V8 NuGet package, and refer to the ReactJS.NET site for more" + "debugging tips.\n\n" + - "More details: " + innerMessage; + "More details: " + innerException.Message; } } } diff --git a/src/React.Core/JavaScriptEngineFactory.cs b/src/React.Core/JavaScriptEngineFactory.cs index 77d920ace..ec017e5e7 100644 --- a/src/React.Core/JavaScriptEngineFactory.cs +++ b/src/React.Core/JavaScriptEngineFactory.cs @@ -234,7 +234,7 @@ private static Func GetFactory(IEnumerable availableFac if (JavaScriptEngineUtils.EnvironmentSupportsClearScript()) { JavaScriptEngineUtils.EnsureEngineFunctional( - ex => new ClearScriptV8InitialisationException(ex.Message) + ex => new ClearScriptV8InitialisationException(ex) ); } else if (JavaScriptEngineUtils.EnvironmentSupportsVroomJs()) From 8c671b9fd40b85f6ce9f1cee30e1e82822a42119 Mon Sep 17 00:00:00 2001 From: Daniel Lo Nigro Date: Sat, 11 Apr 2015 17:36:40 -0700 Subject: [PATCH 006/755] Add JavaScriptEngineSwitcher v8 config section so ClearScript init doesn't fail References https://github.com/Taritsyn/JavaScriptEngineSwitcher/issues/12 --- src/React.Sample.Mvc4/Web.config | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/React.Sample.Mvc4/Web.config b/src/React.Sample.Mvc4/Web.config index 21102e147..33401b4a6 100644 --- a/src/React.Sample.Mvc4/Web.config +++ b/src/React.Sample.Mvc4/Web.config @@ -5,6 +5,11 @@ --> + + +
+ + @@ -57,4 +62,7 @@ + + + From 059a6562c133e223f12d723bb87b99d0a796141d Mon Sep 17 00:00:00 2001 From: Daniel Lo Nigro Date: Sat, 11 Apr 2015 18:02:12 -0700 Subject: [PATCH 007/755] Upgrade React to 0.13.1. Closes #93 --- site/jekyll/getting-started/tutorial.md | 8 +- site/jekyll/guides/cassette.md | 2 +- site/jekyll/guides/server-side-rendering.md | 4 +- site/jekyll/index.md | 2 +- src/React.Core/Resources/JSXTransformer.js | 3637 +++-- src/React.Core/Resources/react-with-addons.js | 11170 +++++++++------- src/React.Core/Resources/shims.js | 2 +- .../Views/Home/Index.cshtml | 2 +- src/React.Sample.Mvc4/Views/Home/Index.cshtml | 2 +- src/React.Sample.Mvc6/Views/Home/Index.cshtml | 2 +- src/React.Sample.Owin/Content/Index.html | 2 +- .../React.Sample.Webpack.csproj | 1 + .../Views/Home/Index.cshtml | 2 +- src/React.Sample.Webpack/package.json | 2 +- 14 files changed, 8658 insertions(+), 6180 deletions(-) diff --git a/site/jekyll/getting-started/tutorial.md b/site/jekyll/getting-started/tutorial.md index db9a31956..16b541a5d 100644 --- a/site/jekyll/getting-started/tutorial.md +++ b/site/jekyll/getting-started/tutorial.md @@ -66,7 +66,7 @@ Replace the contents of the new view file with the following:
- + @@ -235,7 +235,7 @@ Markdown is a simple way to format your text inline. For example, surrounding te First, add the third-party **Showdown** library to your application. This is a JavaScript library which takes Markdown text and converts it to raw HTML. We will add it via NuGet (search for "Showdown" and install it, similar to how you installed ReactJS.NET earlier) and reference the script tag in your view: ```html{2} - + ``` @@ -848,7 +848,7 @@ Now that the bundle has been registered, we need to reference it from the view:
- + @Scripts.Render("~/bundles/main") @Html.ReactInitJavaScript() @@ -934,7 +934,7 @@ In the view, we will accept the list of comments as the model, and use `Html.Rea submitUrl = Url.Action("AddComment"), pollInterval = 2000, }) - + @Html.ReactInitJavaScript() diff --git a/site/jekyll/guides/cassette.md b/site/jekyll/guides/cassette.md index 3d229c512..54f1d58f9 100644 --- a/site/jekyll/guides/cassette.md +++ b/site/jekyll/guides/cassette.md @@ -36,7 +36,7 @@ render from your view using Cassette: ... - + @Bundles.RenderScripts() ``` diff --git a/site/jekyll/guides/server-side-rendering.md b/site/jekyll/guides/server-side-rendering.md index 551f50657..574640ffe 100644 --- a/site/jekyll/guides/server-side-rendering.md +++ b/site/jekyll/guides/server-side-rendering.md @@ -47,7 +47,7 @@ code. ```html - + @Scripts.Render("~/bundles/main") @Html.ReactInitJavaScript() ``` @@ -62,7 +62,7 @@ code. - + ``` diff --git a/site/jekyll/index.md b/site/jekyll/index.md index 34c181281..6b83546b9 100644 --- a/site/jekyll/index.md +++ b/site/jekyll/index.md @@ -112,7 +112,7 @@ bundles.Add(new JsxBundle("~/bundles/main").Include( }) - + @Scripts.Render("~/bundles/main") @Html.ReactInitJavaScript() ``` diff --git a/src/React.Core/Resources/JSXTransformer.js b/src/React.Core/Resources/JSXTransformer.js index 639d15b1c..0cfe4b5d2 100644 --- a/src/React.Core/Resources/JSXTransformer.js +++ b/src/React.Core/Resources/JSXTransformer.js @@ -1,9 +1,9 @@ /** - * JSXTransformer v0.12.2 + * JSXTransformer v0.13.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);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 sourceLines.length) { + return ''; + } var erroneousLine = sourceLines[e.lineNumber - 1]; // Removes any leading indenting spaces and gets the number of @@ -134,7 +133,7 @@ function transformCode(code, url, options) { // The error will correctly point to `url` in Firefox. e.fileName = url; } - e.message += url + ':' + e.lineNumber + ':' + e.column; + e.message += url + ':' + e.lineNumber + ':' + e.columnNumber; } else { e.message += location.href; } @@ -146,10 +145,9 @@ function transformCode(code, url, options) { return transformed.code; } - var map = transformed.sourceMap.toJSON(); var source; if (url == null) { - source = "Inline JSX script"; + source = 'Inline JSX script'; inlineScriptCount++; if (inlineScriptCount > 1) { source += ' (' + inlineScriptCount + ')'; @@ -162,13 +160,11 @@ function transformCode(code, url, options) { 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') + '\n' + + inlineSourceMap(transformed.sourceMap, code, source) ); } @@ -212,7 +208,7 @@ function load(url, successCallback, errorCallback) { successCallback(xhr.responseText); } else { errorCallback(); - throw new Error("Could not load " + url); + throw new Error('Could not load ' + url); } } }; @@ -251,7 +247,7 @@ function loadScripts(scripts) { sourceMap: true }; if (/;harmony=true(;|$)/.test(script.type)) { - options.harmony = true + options.harmony = true; } if (/;stripTypes=true(;|$)/.test(script.type)) { options.stripTypes = true; @@ -326,7 +322,7 @@ function runScripts() { // 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) { +if (typeof window !== 'undefined' && window !== null) { headEl = document.getElementsByTagName('head')[0]; dummyAnchor = document.createElement('a'); @@ -342,7 +338,104 @@ module.exports = { exec: exec }; -},{"./fbtransform/visitors":37,"buffer":2,"jstransform":21,"jstransform/visitors/type-syntax":33}],2:[function(_dereq_,module,exports){ +},{"../main":2,"./inline-source-map":41}],2:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, 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. + */ + +'use strict'; +/*eslint-disable no-undef*/ +var visitors = _dereq_('./vendor/fbtransform/visitors'); +var transform = _dereq_('jstransform').transform; +var typesSyntax = _dereq_('jstransform/visitors/type-syntax'); +var inlineSourceMap = _dereq_('./vendor/inline-source-map'); + +module.exports = { + transform: function(input, options) { + options = processOptions(options); + var output = innerTransform(input, options); + var result = output.code; + if (options.sourceMap) { + var map = inlineSourceMap( + output.sourceMap, + input, + options.filename + ); + result += '\n' + map; + } + return result; + }, + transformWithDetails: function(input, options) { + options = processOptions(options); + var output = innerTransform(input, options); + var result = {}; + result.code = output.code; + if (options.sourceMap) { + result.sourceMap = output.sourceMap.toJSON(); + } + if (options.filename) { + result.sourceMap.sources = [options.filename]; + } + return result; + } +}; + +/** + * Only copy the values that we need. We'll do some preprocessing to account for + * converting command line flags to options that jstransform can actually use. + */ +function processOptions(opts) { + opts = opts || {}; + var options = {}; + + options.harmony = opts.harmony; + options.stripTypes = opts.stripTypes; + options.sourceMap = opts.sourceMap; + options.filename = opts.sourceFilename; + + if (opts.es6module) { + options.sourceType = 'module'; + } + if (opts.nonStrictEs6module) { + options.sourceType = 'nonStrictModule'; + } + + // Instead of doing any fancy validation, only look for 'es3'. If we have + // that, then use it. Otherwise use 'es5'. + options.es3 = opts.target === 'es3'; + options.es5 = !options.es3; + + return options; +} + +function innerTransform(input, options) { + var visitorSets = ['react']; + if (options.harmony) { + visitorSets.push('harmony'); + } + + if (options.es3) { + visitorSets.push('es3'); + } + + 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 + input = transform(typesSyntax.visitorList, input, options).code; + } + + var visitorList = visitors.getVisitorsBySet(visitorSets); + return transform(visitorList, input, options); +} + +},{"./vendor/fbtransform/visitors":40,"./vendor/inline-source-map":41,"jstransform":22,"jstransform/visitors/type-syntax":36}],3:[function(_dereq_,module,exports){ /*! * The buffer module from node.js, for the browser. * @@ -355,11 +448,12 @@ var ieee754 = _dereq_('ieee754') var isArray = _dereq_('is-array') exports.Buffer = Buffer -exports.SlowBuffer = Buffer +exports.SlowBuffer = SlowBuffer exports.INSPECT_MAX_BYTES = 50 Buffer.poolSize = 8192 // not used by this implementation var kMaxLength = 0x3fffffff +var rootParent = {} /** * If `Buffer.TYPED_ARRAY_SUPPORT`: @@ -388,7 +482,7 @@ Buffer.TYPED_ARRAY_SUPPORT = (function () { var buf = new ArrayBuffer(0) var arr = new Uint8Array(buf) arr.foo = function () { return 42 } - return 42 === arr.foo() && // typed array instances can be augmented + return arr.foo() === 42 && // 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) { @@ -409,72 +503,89 @@ Buffer.TYPED_ARRAY_SUPPORT = (function () { * prototype. */ function Buffer (subject, encoding, noZero) { - if (!(this instanceof Buffer)) - return new Buffer(subject, encoding, noZero) + if (!(this instanceof Buffer)) return new Buffer(subject, encoding, noZero) var type = typeof subject - - // Find the length var length - if (type === 'number') - length = subject > 0 ? subject >>> 0 : 0 - else if (type === 'string') { - if (encoding === 'base64') - subject = base64clean(subject) + + if (type === 'number') { + length = +subject + } else if (type === 'string') { length = Buffer.byteLength(subject, encoding) - } else if (type === 'object' && subject !== null) { // assume object is array-like - if (subject.type === 'Buffer' && isArray(subject.data)) - subject = subject.data - length = +subject.length > 0 ? Math.floor(+subject.length) : 0 - } else + } else if (type === 'object' && subject !== null) { + // assume object is array-like + if (subject.type === 'Buffer' && isArray(subject.data)) subject = subject.data + length = +subject.length + } else { throw new TypeError('must start with number, buffer, array or string') + } + + if (length > kMaxLength) { + throw new RangeError('Attempt to allocate Buffer larger than maximum size: 0x' + + kMaxLength.toString(16) + ' bytes') + } - if (this.length > kMaxLength) - throw new RangeError('Attempt to allocate Buffer larger than maximum ' + - 'size: 0x' + kMaxLength.toString(16) + ' bytes') + if (length < 0) length = 0 + else length >>>= 0 // coerce to uint32 - var buf + var self = this if (Buffer.TYPED_ARRAY_SUPPORT) { // Preferred: Return an augmented `Uint8Array` instance for best performance - buf = Buffer._augment(new Uint8Array(length)) + /*eslint-disable consistent-this */ + self = Buffer._augment(new Uint8Array(length)) + /*eslint-enable consistent-this */ } else { // Fallback: Return THIS instance of Buffer (created by `new`) - buf = this - buf.length = length - buf._isBuffer = true + self.length = length + self._isBuffer = true } var i if (Buffer.TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') { // Speed optimization -- use set if we're copying from a typed array - buf._set(subject) + self._set(subject) } else if (isArrayish(subject)) { // Treat array-ish objects as a byte array if (Buffer.isBuffer(subject)) { - for (i = 0; i < length; i++) - buf[i] = subject.readUInt8(i) + for (i = 0; i < length; i++) { + self[i] = subject.readUInt8(i) + } } else { - for (i = 0; i < length; i++) - buf[i] = ((subject[i] % 256) + 256) % 256 + for (i = 0; i < length; i++) { + self[i] = ((subject[i] % 256) + 256) % 256 + } } } else if (type === 'string') { - buf.write(subject, 0, encoding) + self.write(subject, 0, encoding) } else if (type === 'number' && !Buffer.TYPED_ARRAY_SUPPORT && !noZero) { for (i = 0; i < length; i++) { - buf[i] = 0 + self[i] = 0 } } + if (length > 0 && length <= Buffer.poolSize) self.parent = rootParent + + return self +} + +function SlowBuffer (subject, encoding, noZero) { + if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding, noZero) + + var buf = new Buffer(subject, encoding, noZero) + delete buf.parent return buf } -Buffer.isBuffer = function (b) { +Buffer.isBuffer = function isBuffer (b) { return !!(b != null && b._isBuffer) } -Buffer.compare = function (a, b) { - if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) +Buffer.compare = function compare (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { throw new TypeError('Arguments must be Buffers') + } + + if (a === b) return 0 var x = a.length var y = b.length @@ -488,7 +599,7 @@ Buffer.compare = function (a, b) { return 0 } -Buffer.isEncoding = function (encoding) { +Buffer.isEncoding = function isEncoding (encoding) { switch (String(encoding).toLowerCase()) { case 'hex': case 'utf8': @@ -507,7 +618,7 @@ Buffer.isEncoding = function (encoding) { } } -Buffer.concat = function (list, totalLength) { +Buffer.concat = function concat (list, totalLength) { if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])') if (list.length === 0) { @@ -534,7 +645,7 @@ Buffer.concat = function (list, totalLength) { return buf } -Buffer.byteLength = function (str, encoding) { +Buffer.byteLength = function byteLength (str, encoding) { var ret str = str + '' switch (encoding || 'utf8') { @@ -570,7 +681,7 @@ Buffer.prototype.length = undefined Buffer.prototype.parent = undefined // toString(encoding, start=0, end=buffer.length) -Buffer.prototype.toString = function (encoding, start, end) { +Buffer.prototype.toString = function toString (encoding, start, end) { var loweredCase = false start = start >>> 0 @@ -606,43 +717,84 @@ Buffer.prototype.toString = function (encoding, start, end) { return utf16leSlice(this, start, end) default: - if (loweredCase) - throw new TypeError('Unknown encoding: ' + encoding) + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) encoding = (encoding + '').toLowerCase() loweredCase = true } } } -Buffer.prototype.equals = function (b) { - if(!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') +Buffer.prototype.equals = function equals (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true return Buffer.compare(this, b) === 0 } -Buffer.prototype.inspect = function () { +Buffer.prototype.inspect = function inspect () { 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 += ' ... ' + if (this.length > max) str += ' ... ' } return '' } -Buffer.prototype.compare = function (b) { +Buffer.prototype.compare = function compare (b) { if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return 0 return Buffer.compare(this, b) } +Buffer.prototype.indexOf = function indexOf (val, byteOffset) { + if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff + else if (byteOffset < -0x80000000) byteOffset = -0x80000000 + byteOffset >>= 0 + + if (this.length === 0) return -1 + if (byteOffset >= this.length) return -1 + + // Negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0) + + if (typeof val === 'string') { + if (val.length === 0) return -1 // special case: looking for empty string always fails + return String.prototype.indexOf.call(this, val, byteOffset) + } + if (Buffer.isBuffer(val)) { + return arrayIndexOf(this, val, byteOffset) + } + if (typeof val === 'number') { + if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') { + return Uint8Array.prototype.indexOf.call(this, val, byteOffset) + } + return arrayIndexOf(this, [ val ], byteOffset) + } + + function arrayIndexOf (arr, val, byteOffset) { + var foundIndex = -1 + for (var i = 0; byteOffset + i < arr.length; i++) { + if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex + } else { + foundIndex = -1 + } + } + return -1 + } + + throw new TypeError('val must be string, number or Buffer') +} + // `get` will be removed in Node 0.13+ -Buffer.prototype.get = function (offset) { +Buffer.prototype.get = function get (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) { +Buffer.prototype.set = function set (v, offset) { console.log('.set() is deprecated. Access using array indexes instead.') return this.writeUInt8(v, offset) } @@ -667,15 +819,15 @@ function hexWrite (buf, string, offset, length) { length = strLen / 2 } for (var i = 0; i < length; i++) { - var byte = parseInt(string.substr(i * 2, 2), 16) - if (isNaN(byte)) throw new Error('Invalid hex string') - buf[offset + i] = byte + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (isNaN(parsed)) throw new Error('Invalid hex string') + buf[offset + i] = parsed } return i } function utf8Write (buf, string, offset, length) { - var charsWritten = blitBuffer(utf8ToBytes(string), buf, offset, length) + var charsWritten = blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) return charsWritten } @@ -694,11 +846,11 @@ function base64Write (buf, string, offset, length) { } function utf16leWrite (buf, string, offset, length) { - var charsWritten = blitBuffer(utf16leToBytes(string), buf, offset, length) + var charsWritten = blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) return charsWritten } -Buffer.prototype.write = function (string, offset, length, encoding) { +Buffer.prototype.write = function write (string, offset, length, encoding) { // Support both (string, offset, length, encoding) // and the legacy (string, encoding, offset, length) if (isFinite(offset)) { @@ -714,6 +866,11 @@ Buffer.prototype.write = function (string, offset, length, encoding) { } offset = Number(offset) || 0 + + if (length < 0 || offset < 0 || offset > this.length) { + throw new RangeError('attempt to write outside buffer bounds') + } + var remaining = this.length - offset if (!length) { length = remaining @@ -755,7 +912,7 @@ Buffer.prototype.write = function (string, offset, length, encoding) { return ret } -Buffer.prototype.toJSON = function () { +Buffer.prototype.toJSON = function toJSON () { return { type: 'Buffer', data: Array.prototype.slice.call(this._arr || this, 0) @@ -792,13 +949,19 @@ function asciiSlice (buf, start, end) { end = Math.min(buf.length, end) for (var i = start; i < end; i++) { - ret += String.fromCharCode(buf[i]) + ret += String.fromCharCode(buf[i] & 0x7F) } return ret } function binarySlice (buf, start, end) { - return asciiSlice(buf, start, end) + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + ret += String.fromCharCode(buf[i]) + } + return ret } function hexSlice (buf, start, end) { @@ -823,73 +986,99 @@ function utf16leSlice (buf, start, end) { return res } -Buffer.prototype.slice = function (start, end) { +Buffer.prototype.slice = function slice (start, end) { var len = this.length start = ~~start end = end === undefined ? len : ~~end if (start < 0) { - start += len; - if (start < 0) - start = 0 + start += len + if (start < 0) start = 0 } else if (start > len) { start = len } if (end < 0) { end += len - if (end < 0) - end = 0 + if (end < 0) end = 0 } else if (end > len) { end = len } - if (end < start) - end = start + if (end < start) end = start + var newBuf if (Buffer.TYPED_ARRAY_SUPPORT) { - return Buffer._augment(this.subarray(start, end)) + newBuf = Buffer._augment(this.subarray(start, end)) } else { var sliceLen = end - start - var newBuf = new Buffer(sliceLen, undefined, true) + newBuf = new Buffer(sliceLen, undefined, true) for (var i = 0; i < sliceLen; i++) { newBuf[i] = this[i + start] } - return newBuf } + + if (newBuf.length) newBuf.parent = this.parent || this + + return newBuf } /* * 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') + 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.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val } -Buffer.prototype.readUInt8 = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 1, this.length) +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) return this[offset] } -Buffer.prototype.readUInt16LE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 2, this.length) +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) return this[offset] | (this[offset + 1] << 8) } -Buffer.prototype.readUInt16BE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 2, this.length) +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) return (this[offset] << 8) | this[offset + 1] } -Buffer.prototype.readUInt32LE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) return ((this[offset]) | (this[offset + 1] << 8) | @@ -897,93 +1086,149 @@ Buffer.prototype.readUInt32LE = function (offset, noAssert) { (this[offset + 3] * 0x1000000) } -Buffer.prototype.readUInt32BE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset] * 0x1000000) + - ((this[offset + 1] << 16) | - (this[offset + 2] << 8) | - this[offset + 3]) + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val } -Buffer.prototype.readInt8 = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 1, this.length) - if (!(this[offset] & 0x80)) - return (this[offset]) +Buffer.prototype.readInt8 = function readInt8 (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) { - if (!noAssert) - checkOffset(offset, 2, this.length) +Buffer.prototype.readInt16LE = function readInt16LE (offset, 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) { - if (!noAssert) - checkOffset(offset, 2, this.length) +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + 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) { - if (!noAssert) - checkOffset(offset, 4, this.length) +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16) | - (this[offset + 3] << 24) + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) } -Buffer.prototype.readInt32BE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) +Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset] << 24) | - (this[offset + 1] << 16) | - (this[offset + 2] << 8) | - (this[offset + 3]) + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) } -Buffer.prototype.readFloatLE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) return ieee754.read(this, offset, true, 23, 4) } -Buffer.prototype.readFloatBE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) return ieee754.read(this, offset, false, 23, 4) } -Buffer.prototype.readDoubleLE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 8, this.length) +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) return ieee754.read(this, offset, true, 52, 8) } -Buffer.prototype.readDoubleBE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 8, this.length) +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) return ieee754.read(this, offset, false, 52, 8) } 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') + if (value > max || value < min) throw new RangeError('value is out of bounds') + if (offset + ext > buf.length) throw new RangeError('index out of range') +} + +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) >>> 0 & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) >>> 0 & 0xFF + } + + return offset + byteLength } -Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { value = +value offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 1, 0xff, 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 @@ -997,27 +1242,29 @@ function objectWriteUInt16 (buf, value, offset, littleEndian) { } } -Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { value = +value offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 2, 0xffff, 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) + } else { + objectWriteUInt16(this, value, offset, true) + } return offset + 2 } -Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { value = +value offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 2, 0xffff, 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) + } else { + objectWriteUInt16(this, value, offset, false) + } return offset + 2 } @@ -1028,157 +1275,211 @@ function objectWriteUInt32 (buf, value, offset, littleEndian) { } } -Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { value = +value offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 4, 0xffffffff, 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) + } else { + objectWriteUInt32(this, value, offset, true) + } return offset + 4 } -Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { value = +value offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 4, 0xffffffff, 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) + } else { + objectWriteUInt32(this, value, offset, false) + } return offset + 4 } -Buffer.prototype.writeInt8 = function (value, offset, noAssert) { +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkInt( + this, value, offset, byteLength, + Math.pow(2, 8 * byteLength - 1) - 1, + -Math.pow(2, 8 * byteLength - 1) + ) + } + + var i = 0 + var mul = 1 + var sub = value < 0 ? 1 : 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkInt( + this, value, offset, byteLength, + Math.pow(2, 8 * byteLength - 1) - 1, + -Math.pow(2, 8 * byteLength - 1) + ) + } + + var i = byteLength - 1 + var mul = 1 + var sub = value < 0 ? 1 : 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 1, 0x7f, -0x80) + 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 } -Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { +Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 2, 0x7fff, -0x8000) + 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) + } else { + objectWriteUInt16(this, value, offset, true) + } return offset + 2 } -Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { +Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 2, 0x7fff, -0x8000) + 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) + } else { + objectWriteUInt16(this, value, offset, false) + } return offset + 2 } -Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { +Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + 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) + } else { + objectWriteUInt32(this, value, offset, true) + } return offset + 4 } -Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { +Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + 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) + } else { + objectWriteUInt32(this, value, offset, false) + } return offset + 4 } 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') + if (value > max || value < min) throw new RangeError('value is out of bounds') + if (offset + ext > buf.length) throw new RangeError('index out of range') + if (offset < 0) throw new RangeError('index out of range') } function writeFloat (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) + if (!noAssert) { checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } ieee754.write(buf, value, offset, littleEndian, 23, 4) return offset + 4 } -Buffer.prototype.writeFloatLE = function (value, offset, noAssert) { +Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { return writeFloat(this, value, offset, true, noAssert) } -Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { +Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { return writeFloat(this, value, offset, false, noAssert) } function writeDouble (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) + if (!noAssert) { checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } ieee754.write(buf, value, offset, littleEndian, 52, 8) return offset + 8 } -Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) { +Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { return writeDouble(this, value, offset, true, noAssert) } -Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { +Buffer.prototype.writeDoubleBE = function writeDoubleBE (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 +Buffer.prototype.copy = function copy (target, target_start, start, end) { + var self = this // source if (!start) start = 0 if (!end && end !== 0) end = this.length + if (target_start >= target.length) target_start = target.length if (!target_start) target_start = 0 + if (end > 0 && end < start) end = start // Copy 0 bytes; we're done - if (end === start) return - if (target.length === 0 || source.length === 0) return + if (end === start) return 0 + if (target.length === 0 || self.length === 0) return 0 // 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') + if (target_start < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= self.length) throw new RangeError('sourceStart out of bounds') + if (end < 0) throw new RangeError('sourceEnd out of bounds') // Are we oob? - if (end > this.length) - end = this.length - if (target.length - target_start < end - start) + if (end > this.length) end = this.length + if (target.length - target_start < end - start) { end = target.length - target_start + start + } var len = end - start @@ -1189,22 +1490,24 @@ Buffer.prototype.copy = function (target, target_start, start, end) { } else { target._set(this.subarray(start, start + len), target_start) } + + return len } // fill(value, start=0, end=buffer.length) -Buffer.prototype.fill = function (value, start, end) { +Buffer.prototype.fill = function fill (value, start, end) { if (!value) value = 0 if (!start) start = 0 if (!end) end = this.length - if (end < start) throw new TypeError('end < start') + if (end < start) throw new RangeError('end < start') // Fill 0 bytes; we're done if (end === start) return if (this.length === 0) return - 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') + if (start < 0 || start >= this.length) throw new RangeError('start out of bounds') + if (end < 0 || end > this.length) throw new RangeError('end out of bounds') var i if (typeof value === 'number') { @@ -1226,7 +1529,7 @@ Buffer.prototype.fill = function (value, start, end) { * 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 () { +Buffer.prototype.toArrayBuffer = function toArrayBuffer () { if (typeof Uint8Array !== 'undefined') { if (Buffer.TYPED_ARRAY_SUPPORT) { return (new Buffer(this)).buffer @@ -1250,7 +1553,7 @@ var BP = Buffer.prototype /** * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods */ -Buffer._augment = function (arr) { +Buffer._augment = function _augment (arr) { arr.constructor = Buffer arr._isBuffer = true @@ -1268,13 +1571,18 @@ Buffer._augment = function (arr) { arr.toJSON = BP.toJSON arr.equals = BP.equals arr.compare = BP.compare + arr.indexOf = BP.indexOf arr.copy = BP.copy arr.slice = BP.slice + arr.readUIntLE = BP.readUIntLE + arr.readUIntBE = BP.readUIntBE arr.readUInt8 = BP.readUInt8 arr.readUInt16LE = BP.readUInt16LE arr.readUInt16BE = BP.readUInt16BE arr.readUInt32LE = BP.readUInt32LE arr.readUInt32BE = BP.readUInt32BE + arr.readIntLE = BP.readIntLE + arr.readIntBE = BP.readIntBE arr.readInt8 = BP.readInt8 arr.readInt16LE = BP.readInt16LE arr.readInt16BE = BP.readInt16BE @@ -1285,10 +1593,14 @@ Buffer._augment = function (arr) { arr.readDoubleLE = BP.readDoubleLE arr.readDoubleBE = BP.readDoubleBE arr.writeUInt8 = BP.writeUInt8 + arr.writeUIntLE = BP.writeUIntLE + arr.writeUIntBE = BP.writeUIntBE arr.writeUInt16LE = BP.writeUInt16LE arr.writeUInt16BE = BP.writeUInt16BE arr.writeUInt32LE = BP.writeUInt32LE arr.writeUInt32BE = BP.writeUInt32BE + arr.writeIntLE = BP.writeIntLE + arr.writeIntBE = BP.writeIntBE arr.writeInt8 = BP.writeInt8 arr.writeInt16LE = BP.writeInt16LE arr.writeInt16BE = BP.writeInt16BE @@ -1305,11 +1617,13 @@ Buffer._augment = function (arr) { return arr } -var INVALID_BASE64_RE = /[^+\/0-9A-z]/g +var INVALID_BASE64_RE = /[^+\/0-9A-z\-]/g function base64clean (str) { // Node strips out invalid characters like \n and \t from the string, base64-js does not str = stringtrim(str).replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not while (str.length % 4 !== 0) { str = str + '=' @@ -1333,22 +1647,85 @@ function toHex (n) { return n.toString(16) } -function utf8ToBytes (str) { - var byteArray = [] - for (var i = 0; i < str.length; i++) { - var b = str.charCodeAt(i) - if (b <= 0x7F) { - byteArray.push(b) - } else { - var start = i - if (b >= 0xD800 && b <= 0xDFFF) i++ - var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%') - for (var j = 0; j < h.length; j++) { - byteArray.push(parseInt(h[j], 16)) +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + var i = 0 + + for (; i < length; i++) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (leadSurrogate) { + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } else { + // valid surrogate pair + codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000 + leadSurrogate = null + } + } else { + // no lead yet + + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else { + // valid lead + leadSurrogate = codePoint + continue + } } + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = null + } + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x200000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') } } - return byteArray + + return bytes } function asciiToBytes (str) { @@ -1360,10 +1737,12 @@ function asciiToBytes (str) { return byteArray } -function utf16leToBytes (str) { +function utf16leToBytes (str, units) { var c, hi, lo var byteArray = [] for (var i = 0; i < str.length; i++) { + if ((units -= 2) < 0) break + c = str.charCodeAt(i) hi = c >> 8 lo = c % 256 @@ -1375,13 +1754,12 @@ function utf16leToBytes (str) { } function base64ToBytes (str) { - return base64.toByteArray(str) + return base64.toByteArray(base64clean(str)) } function blitBuffer (src, dst, offset, length) { for (var i = 0; i < length; i++) { - if ((i + offset >= dst.length) || (i >= src.length)) - break + if ((i + offset >= dst.length) || (i >= src.length)) break dst[i + offset] = src[i] } return i @@ -1395,7 +1773,7 @@ function decodeUtf8Char (str) { } } -},{"base64-js":3,"ieee754":4,"is-array":5}],3:[function(_dereq_,module,exports){ +},{"base64-js":4,"ieee754":5,"is-array":6}],4:[function(_dereq_,module,exports){ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; ;(function (exports) { @@ -1410,12 +1788,16 @@ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; var NUMBER = '0'.charCodeAt(0) var LOWER = 'a'.charCodeAt(0) var UPPER = 'A'.charCodeAt(0) + var PLUS_URL_SAFE = '-'.charCodeAt(0) + var SLASH_URL_SAFE = '_'.charCodeAt(0) function decode (elt) { var code = elt.charCodeAt(0) - if (code === PLUS) + if (code === PLUS || + code === PLUS_URL_SAFE) return 62 // '+' - if (code === SLASH) + if (code === SLASH || + code === SLASH_URL_SAFE) return 63 // '/' if (code < NUMBER) return -1 //no match @@ -1517,7 +1899,7 @@ var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; exports.fromByteArray = uint8ToBase64 }(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) -},{}],4:[function(_dereq_,module,exports){ +},{}],5:[function(_dereq_,module,exports){ exports.read = function(buffer, offset, isLE, mLen, nBytes) { var e, m, eLen = nBytes * 8 - mLen - 1, @@ -1603,7 +1985,7 @@ exports.write = function(buffer, value, offset, isLE, mLen, nBytes) { buffer[offset + i - d] |= s * 128; }; -},{}],5:[function(_dereq_,module,exports){ +},{}],6:[function(_dereq_,module,exports){ /** * isArray @@ -1638,7 +2020,7 @@ module.exports = isArray || function (val) { return !! val && '[object Array]' == str.call(val); }; -},{}],6:[function(_dereq_,module,exports){ +},{}],7:[function(_dereq_,module,exports){ (function (process){ // Copyright Joyent, Inc. and other Node contributors. // @@ -1866,73 +2248,44 @@ var substr = 'ab'.substr(-1) === 'b' ; }).call(this,_dereq_('_process')) -},{"_process":7}],7:[function(_dereq_,module,exports){ +},{"_process":8}],8:[function(_dereq_,module,exports){ // shim for using process in browser var process = module.exports = {}; +var queue = []; +var draining = false; -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 - ; - - if (canSetImmediate) { - return function (f) { return window.setImmediate(f) }; +function drainQueue() { + if (draining) { + return; } - - 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); - }; + draining = true; + var currentQueue; + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + var i = -1; + while (++i < len) { + currentQueue[i](); + } + len = queue.length; } - - if (canPost) { - window.addEventListener('message', function (ev) { - var source = ev.source; - if ((source === window || source === null) && ev.data === 'process-tick') { - ev.stopPropagation(); - if (queue.length > 0) { - var fn = queue.shift(); - fn(); - } - } - }, true); - - return function nextTick(fn) { - queue.push(fn); - window.postMessage('process-tick', '*'); - }; + draining = false; +} +process.nextTick = function (fun) { + queue.push(fun); + if (!draining) { + setTimeout(drainQueue, 0); } - - return function nextTick(fn) { - setTimeout(fn, 0); - }; -})(); +}; process.title = 'browser'; process.browser = true; process.env = {}; process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; function noop() {} @@ -1953,35 +2306,8 @@ process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; +process.umask = function() { return 0; }; -},{}],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 @@ -2015,35 +2341,13 @@ module.exports = Base62 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/*jslint bitwise:true plusplus:true */ -/*global esprima:true, define:true, exports:true, window: true, -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, parseInterface: true, -parseLeftHandSideExpression: true, parseParams: true, validateParam: true, -parseSpreadOrAssignmentExpression: 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, -parseFunctionTypeParam: true, -parsePrimaryType: true, -parseTypeAlias: true, -parseType: true, parseTypeAnnotatableIdentifier: true, parseTypeAnnotation: true, -parseYieldExpression: true, parseAwaitExpression: true -*/ - (function (root, factory) { 'use strict'; // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, // Rhino, and plain browser loading. + + /* istanbul ignore next */ if (typeof define === 'function' && define.amd) { define(['exports'], factory); } else if (typeof exports !== 'undefined') { @@ -2086,8 +2390,8 @@ parseYieldExpression: true, parseAwaitExpression: true StringLiteral: 8, RegularExpression: 9, Template: 10, - XJSIdentifier: 11, - XJSText: 12 + JSXIdentifier: 11, + JSXText: 12 }; TokenName = {}; @@ -2099,8 +2403,8 @@ parseYieldExpression: true, parseAwaitExpression: true TokenName[Token.NumericLiteral] = 'Numeric'; TokenName[Token.Punctuator] = 'Punctuator'; TokenName[Token.StringLiteral] = 'String'; - TokenName[Token.XJSIdentifier] = 'XJSIdentifier'; - TokenName[Token.XJSText] = 'XJSText'; + TokenName[Token.JSXIdentifier] = 'JSXIdentifier'; + TokenName[Token.JSXText] = 'JSXText'; TokenName[Token.RegularExpression] = 'RegularExpression'; // A function following one of those tokens is an expression. @@ -2199,6 +2503,7 @@ parseYieldExpression: true, parseAwaitExpression: true TryStatement: 'TryStatement', TypeAlias: 'TypeAlias', TypeAnnotation: 'TypeAnnotation', + TypeCastExpression: 'TypeCastExpression', TypeofTypeAnnotation: 'TypeofTypeAnnotation', TypeParameterDeclaration: 'TypeParameterDeclaration', TypeParameterInstantiation: 'TypeParameterInstantiation', @@ -2210,17 +2515,17 @@ parseYieldExpression: true, parseAwaitExpression: true VoidTypeAnnotation: 'VoidTypeAnnotation', WhileStatement: 'WhileStatement', WithStatement: 'WithStatement', - XJSIdentifier: 'XJSIdentifier', - XJSNamespacedName: 'XJSNamespacedName', - XJSMemberExpression: 'XJSMemberExpression', - XJSEmptyExpression: 'XJSEmptyExpression', - XJSExpressionContainer: 'XJSExpressionContainer', - XJSElement: 'XJSElement', - XJSClosingElement: 'XJSClosingElement', - XJSOpeningElement: 'XJSOpeningElement', - XJSAttribute: 'XJSAttribute', - XJSSpreadAttribute: 'XJSSpreadAttribute', - XJSText: 'XJSText', + JSXIdentifier: 'JSXIdentifier', + JSXNamespacedName: 'JSXNamespacedName', + JSXMemberExpression: 'JSXMemberExpression', + JSXEmptyExpression: 'JSXEmptyExpression', + JSXExpressionContainer: 'JSXExpressionContainer', + JSXElement: 'JSXElement', + JSXClosingElement: 'JSXClosingElement', + JSXOpeningElement: 'JSXOpeningElement', + JSXAttribute: 'JSXAttribute', + JSXSpreadAttribute: 'JSXSpreadAttribute', + JSXText: 'JSXText', YieldExpression: 'YieldExpression', AwaitExpression: 'AwaitExpression' }; @@ -2238,32 +2543,33 @@ parseYieldExpression: true, parseAwaitExpression: true // Error messages should be identical to V8. Messages = { - UnexpectedToken: 'Unexpected token %0', - UnexpectedNumber: 'Unexpected number', - UnexpectedString: 'Unexpected string', - UnexpectedIdentifier: 'Unexpected identifier', - UnexpectedReserved: 'Unexpected reserved word', - UnexpectedTemplate: 'Unexpected quasi %0', - UnexpectedEOS: 'Unexpected end of input', - NewlineAfterThrow: 'Illegal newline after throw', + UnexpectedToken: 'Unexpected token %0', + UnexpectedNumber: 'Unexpected number', + UnexpectedString: 'Unexpected string', + UnexpectedIdentifier: 'Unexpected identifier', + UnexpectedReserved: 'Unexpected reserved word', + UnexpectedTemplate: 'Unexpected quasi %0', + UnexpectedEOS: 'Unexpected end of input', + NewlineAfterThrow: 'Illegal newline after throw', InvalidRegExp: 'Invalid regular expression', - UnterminatedRegExp: 'Invalid regular expression: missing /', - InvalidLHSInAssignment: 'Invalid left-hand side in assignment', - InvalidLHSInFormalsList: 'Invalid left-hand side in formals list', - InvalidLHSInForIn: 'Invalid left-hand side in for-in', + UnterminatedRegExp: 'Invalid regular expression: missing /', + InvalidLHSInAssignment: 'Invalid left-hand side in assignment', + InvalidLHSInFormalsList: 'Invalid left-hand side in formals list', + InvalidLHSInForIn: 'Invalid left-hand side in for-in', MultipleDefaultsInSwitch: 'More than one default clause in switch statement', - NoCatchOrFinally: 'Missing catch or finally after try', + NoCatchOrFinally: 'Missing catch or finally after try', UnknownLabel: 'Undefined label \'%0\'', Redeclaration: '%0 \'%1\' has already been declared', IllegalContinue: 'Illegal continue statement', IllegalBreak: 'Illegal break statement', IllegalDuplicateClassProperty: 'Illegal duplicate property in class definition', + IllegalClassConstructorProperty: 'Illegal constructor property in class definition', IllegalReturn: 'Illegal return statement', 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', - StrictVarName: 'Variable name may not be eval or arguments in strict mode', - StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', + StrictModeWith: 'Strict mode code may not include a with statement', + StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', + StrictVarName: 'Variable name may not be eval or arguments in strict mode', + StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', StrictParamDupe: 'Strict mode function may not have duplicate parameter names', ParameterAfterRestParameter: 'Rest parameter must be final parameter of an argument list', DefaultRestParameter: 'Rest parameter can not have a default value', @@ -2271,26 +2577,28 @@ parseYieldExpression: true, parseAwaitExpression: true PropertyAfterSpreadProperty: 'A rest property must be the final property of an object literal', ObjectPatternAsRestParameter: 'Invalid rest parameter', ObjectPatternAsSpread: 'Invalid spread argument', - StrictFunctionName: 'Function name may not be eval or arguments in strict mode', - StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', - StrictDelete: 'Delete of an unqualified identifier in strict mode.', - StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', - AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', - AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', - StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', - 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', + StrictFunctionName: 'Function name may not be eval or arguments in strict mode', + StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', + StrictDelete: 'Delete of an unqualified identifier in strict mode.', + StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', + AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', + AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', + StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', + 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', MissingFromClause: 'Missing from clause', NoAsAfterImportNamespace: 'Missing as after import *', InvalidModuleSpecifier: 'Invalid module specifier', - NoUnintializedConst: 'Const must be initialized', + IllegalImportDeclaration: 'Illegal import declaration', + IllegalExportDeclaration: 'Illegal export declaration', + NoUninitializedConst: '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', + ComprehensionError: 'Comprehension Error', + EachNotAllowed: 'Each is not supported', + InvalidJSXAttributeValue: 'JSX value should be either an expression or a quoted JSX text', + ExpectedJSXClosingTag: 'Expected corresponding JSX closing tag for %0', + AdjacentJSXElements: 'Adjacent JSX 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 ' + @@ -2312,17 +2620,43 @@ parseYieldExpression: true, parseAwaitExpression: true // Do NOT use this to enforce a certain condition on any user input. function assert(condition, message) { + /* istanbul ignore if */ if (!condition) { throw new Error('ASSERT: ' + message); } } - function isDecimalDigit(ch) { - return (ch >= 48 && ch <= 57); // 0..9 + function StringMap() { + this.$data = {}; } - function isHexDigit(ch) { - return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; + StringMap.prototype.get = function (key) { + key = '$' + key; + return this.$data[key]; + }; + + StringMap.prototype.set = function (key, value) { + key = '$' + key; + this.$data[key] = value; + return this; + }; + + StringMap.prototype.has = function (key) { + key = '$' + key; + return Object.prototype.hasOwnProperty.call(this.$data, key); + }; + + StringMap.prototype["delete"] = function (key) { + key = '$' + key; + return delete this.$data[key]; + }; + + function isDecimalDigit(ch) { + return (ch >= 48 && ch <= 57); // 0..9 + } + + function isHexDigit(ch) { + return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; } function isOctalDigit(ch) { @@ -2444,69 +2778,134 @@ parseYieldExpression: true, parseAwaitExpression: true // 7.4 Comments - function skipComment() { - var ch, blockComment, lineComment; + function addComment(type, value, start, end, loc) { + var comment; + assert(typeof start === 'number', 'Comment must have valid position'); + + // Because the way the actual token is scanned, often the comments + // (if any) are skipped twice during the lexical analysis. + // Thus, we need to skip adding a comment if the comment array already + // handled it. + if (state.lastCommentStart >= start) { + return; + } + state.lastCommentStart = start; + + comment = { + type: type, + value: value + }; + if (extra.range) { + comment.range = [start, end]; + } + if (extra.loc) { + comment.loc = loc; + } + extra.comments.push(comment); + if (extra.attachComment) { + extra.leadingComments.push(comment); + extra.trailingComments.push(comment); + } + } - blockComment = false; - lineComment = false; + function skipSingleLineComment() { + var start, loc, ch, comment; + + start = index - 2; + loc = { + start: { + line: lineNumber, + column: index - lineStart - 2 + } + }; while (index < length) { ch = source.charCodeAt(index); + ++index; + if (isLineTerminator(ch)) { + if (extra.comments) { + comment = source.slice(start + 2, index - 1); + loc.end = { + line: lineNumber, + column: index - lineStart - 1 + }; + addComment('Line', comment, start, index - 1, loc); + } + if (ch === 13 && source.charCodeAt(index) === 10) { + ++index; + } + ++lineNumber; + lineStart = index; + return; + } + } - if (lineComment) { - ++index; - if (isLineTerminator(ch)) { - lineComment = false; - if (ch === 13 && source.charCodeAt(index) === 10) { - ++index; - } - ++lineNumber; - lineStart = index; + if (extra.comments) { + comment = source.slice(start + 2, index); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + addComment('Line', comment, start, index, loc); + } + } + + function skipMultiLineComment() { + var start, loc, ch, comment; + + if (extra.comments) { + start = index - 2; + loc = { + start: { + line: lineNumber, + column: index - lineStart - 2 } - } else if (blockComment) { - if (isLineTerminator(ch)) { - if (ch === 13) { - ++index; - } - if (ch !== 13 || source.charCodeAt(index) === 10) { - ++lineNumber; - ++index; - lineStart = index; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - } else { - ch = source.charCodeAt(index++); - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - // Block comment ends with '*/' (char #42, char #47). - if (ch === 42) { - ch = source.charCodeAt(index); - if (ch === 47) { - ++index; - blockComment = false; - } - } + }; + } + + while (index < length) { + ch = source.charCodeAt(index); + if (isLineTerminator(ch)) { + if (ch === 13 && source.charCodeAt(index + 1) === 10) { + ++index; } - } else if (ch === 47) { - ch = source.charCodeAt(index + 1); - // Line comment starts with '//' (char #47, char #47). - if (ch === 47) { - index += 2; - lineComment = true; - } else if (ch === 42) { - // Block comment starts with '/*' (char #47, char #42). - index += 2; - blockComment = true; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else if (ch === 42) { + // Block comment ends with '*/' (char #42, char #47). + if (source.charCodeAt(index + 1) === 47) { + ++index; + ++index; + if (extra.comments) { + comment = source.slice(start + 2, index - 2); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + addComment('Block', comment, start, index, loc); } - } else { - break; + return; } - } else if (isWhiteSpace(ch)) { + ++index; + } else { + ++index; + } + } + + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + function skipComment() { + var ch; + + while (index < length) { + ch = source.charCodeAt(index); + + if (isWhiteSpace(ch)) { ++index; } else if (isLineTerminator(ch)) { ++index; @@ -2515,6 +2914,19 @@ parseYieldExpression: true, parseAwaitExpression: true } ++lineNumber; lineStart = index; + } else if (ch === 47) { // 47 is '/' + ch = source.charCodeAt(index + 1); + if (ch === 47) { + ++index; + ++index; + skipSingleLineComment(); + } else if (ch === 42) { // 42 is '*' + ++index; + ++index; + skipMultiLineComment(); + } else { + break; + } } else { break; } @@ -2677,6 +3089,23 @@ parseYieldExpression: true, parseAwaitExpression: true ch3, ch4; + if (state.inJSXTag || state.inJSXChild) { + // Don't need to check for '{' and '}' as it's already handled + // correctly by default. + switch (code) { + case 60: // < + case 62: // > + ++index; + return { + type: Token.Punctuator, + value: String.fromCharCode(code), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + } + switch (code) { // Check for most common single-character punctuators. case 40: // ( open bracket @@ -2776,7 +3205,7 @@ parseYieldExpression: true, parseAwaitExpression: true // 3-character punctuators: === !== >>> <<= >>= - if (ch1 === '>' && ch2 === '>' && ch3 === '>') { + if (ch1 === '>' && ch2 === '>' && ch3 === '>' && !state.inType) { index += 3; return { type: Token.Punctuator, @@ -2900,6 +3329,41 @@ parseYieldExpression: true, parseAwaitExpression: true }; } + function scanBinaryLiteral(start) { + var ch, number; + + number = ''; + + while (index < length) { + ch = source.charAt(index); + if (ch !== '0' && ch !== '1') { + break; + } + number += source.charAt(index++); + } + + if (number.length === 0) { + // only 0b or 0B + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + if (index < length) { + ch = source.charCodeAt(index); + /* istanbul ignore else */ + if (isIdentifierStart(ch) || isDecimalDigit(ch)) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + + return { + type: Token.NumericLiteral, + value: parseInt(number, 2), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + function scanOctalLiteral(prefix, start) { var number, octal; @@ -2939,7 +3403,7 @@ parseYieldExpression: true, parseAwaitExpression: true } function scanNumericLiteral() { - var number, start, ch, octal; + var number, start, ch; ch = source.charAt(index); assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), @@ -2962,34 +3426,7 @@ parseYieldExpression: true, parseAwaitExpression: true } if (ch === 'b' || ch === 'B') { ++index; - number = ''; - - while (index < length) { - ch = source.charAt(index); - if (ch !== '0' && ch !== '1') { - break; - } - number += source.charAt(index++); - } - - if (number.length === 0) { - // only 0b or 0B - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - - if (index < length) { - ch = source.charCodeAt(index); - if (isIdentifierStart(ch) || isDecimalDigit(ch)) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - return { - type: Token.NumericLiteral, - value: parseInt(number, 2), - lineNumber: lineNumber, - lineStart: lineStart, - range: [start, index] - }; + return scanBinaryLiteral(start); } if (ch === 'o' || ch === 'O' || isOctalDigit(ch)) { return scanOctalLiteral(ch, start); @@ -3109,6 +3546,7 @@ parseYieldExpression: true, parseAwaitExpression: true octal = true; } + /* istanbul ignore else */ if (index < length && isOctalDigit(source.charAt(index))) { octal = true; code = code * 8 + '01234567'.indexOf(source.charAt(index++)); @@ -3129,7 +3567,7 @@ parseYieldExpression: true, parseAwaitExpression: true } } else { ++lineNumber; - if (ch === '\r' && source.charAt(index) === '\n') { + if (ch === '\r' && source.charAt(index) === '\n') { ++index; } lineStart = index; @@ -3225,6 +3663,7 @@ parseYieldExpression: true, parseAwaitExpression: true octal = true; } + /* istanbul ignore else */ if (index < length && isOctalDigit(source.charAt(index))) { octal = true; code = code * 8 + '01234567'.indexOf(source.charAt(index++)); @@ -3245,14 +3684,14 @@ parseYieldExpression: true, parseAwaitExpression: true } } else { ++lineNumber; - if (ch === '\r' && source.charAt(index) === '\n') { + if (ch === '\r' && source.charAt(index) === '\n') { ++index; } lineStart = index; } } else if (isLineTerminator(ch.charCodeAt(0))) { ++lineNumber; - if (ch === '\r' && source.charAt(index) === '\n') { + if (ch === '\r' && source.charAt(index) === '\n') { ++index; } lineStart = index; @@ -3299,39 +3738,77 @@ parseYieldExpression: true, parseAwaitExpression: true return template; } - function scanRegExp() { - var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false, tmp; + function testRegExp(pattern, flags) { + var tmp = pattern, + value; - lookahead = null; - skipComment(); + if (flags.indexOf('u') >= 0) { + // Replace each astral symbol and every Unicode code point + // escape sequence with a single ASCII symbol to avoid throwing on + // regular expressions that are only valid in combination with the + // `/u` flag. + // Note: replacing with the ASCII symbol `x` might cause false + // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a + // perfectly valid pattern that is equivalent to `[a-b]`, but it + // would be replaced by `[x-b]` which throws an error. + tmp = tmp + .replace(/\\u\{([0-9a-fA-F]+)\}/g, function ($0, $1) { + if (parseInt($1, 16) <= 0x10FFFF) { + return 'x'; + } + throwError({}, Messages.InvalidRegExp); + }) + .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x'); + } + + // First, detect invalid regular expressions. + try { + value = new RegExp(tmp); + } catch (e) { + throwError({}, Messages.InvalidRegExp); + } + + // 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 { + return new RegExp(pattern, flags); + } catch (exception) { + return null; + } + } + + function scanRegExpBody() { + var ch, str, classMarker, terminated, body; - start = index; ch = source.charAt(index); assert(ch === '/', 'Regular expression literal must start with a slash'); str = source.charAt(index++); + classMarker = false; + terminated = false; while (index < length) { ch = source.charAt(index++); str += ch; - if (classMarker) { + if (ch === '\\') { + ch = source.charAt(index++); + // ECMA-262 7.8.5 + if (isLineTerminator(ch.charCodeAt(0))) { + throwError({}, Messages.UnterminatedRegExp); + } + str += ch; + } else if (isLineTerminator(ch.charCodeAt(0))) { + throwError({}, Messages.UnterminatedRegExp); + } else if (classMarker) { if (ch === ']') { classMarker = false; } } else { - if (ch === '\\') { - ch = source.charAt(index++); - // ECMA-262 7.8.5 - if (isLineTerminator(ch.charCodeAt(0))) { - throwError({}, Messages.UnterminatedRegExp); - } - str += ch; - } else if (ch === '/') { + if (ch === '/') { terminated = true; break; } else if (ch === '[') { classMarker = true; - } else if (isLineTerminator(ch.charCodeAt(0))) { - throwError({}, Messages.UnterminatedRegExp); } } } @@ -3341,8 +3818,17 @@ parseYieldExpression: true, parseAwaitExpression: true } // Exclude leading and trailing slash. - pattern = str.substr(1, str.length - 2); + body = str.substr(1, str.length - 2); + return { + value: body, + literal: str + }; + } + + function scanRegExpFlags() { + var ch, str, flags, restore; + str = ''; flags = ''; while (index < length) { ch = source.charAt(index); @@ -3367,8 +3853,10 @@ parseYieldExpression: true, parseAwaitExpression: true flags += 'u'; str += '\\u'; } + throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL'); } else { str += '\\'; + throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL'); } } else { flags += ch; @@ -3376,54 +3864,43 @@ parseYieldExpression: true, parseAwaitExpression: 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(tmp); - } catch (e) { - throwError({}, Messages.InvalidRegExp); - } + return { + value: flags, + literal: str + }; + } - // 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; - } + function scanRegExp() { + var start, body, flags, value; - peek(); + lookahead = null; + skipComment(); + start = index; + + body = scanRegExpBody(); + flags = scanRegExpFlags(); + value = testRegExp(body.value, flags.value); if (extra.tokenize) { return { type: Token.RegularExpression, value: value, regex: { - pattern: pattern, - flags: flags + pattern: body.value, + flags: flags.value }, lineNumber: lineNumber, lineStart: lineStart, range: [start, index] }; } + return { - literal: str, + literal: body.literal + flags.literal, value: value, regex: { - pattern: pattern, - flags: flags + pattern: body.value, + flags: flags.value }, range: [start, index] }; @@ -3490,7 +3967,7 @@ parseYieldExpression: true, parseAwaitExpression: true } return scanRegExp(); } - if (prevToken.type === 'Keyword') { + if (prevToken.type === 'Keyword' && prevToken.value !== 'this') { return scanRegExp(); } return scanPunctuator(); @@ -3499,7 +3976,7 @@ parseYieldExpression: true, parseAwaitExpression: true function advance() { var ch; - if (!state.inXJSChild) { + if (!state.inJSXChild) { skipComment(); } @@ -3512,8 +3989,8 @@ parseYieldExpression: true, parseAwaitExpression: true }; } - if (state.inXJSChild) { - return advanceXJSChild(); + if (state.inJSXChild) { + return advanceJSXChild(); } ch = source.charCodeAt(index); @@ -3525,14 +4002,14 @@ parseYieldExpression: true, parseAwaitExpression: true // String literal starts with single quote (#39) or double quote (#34). if (ch === 39 || ch === 34) { - if (state.inXJSTag) { - return scanXJSStringLiteral(); + if (state.inJSXTag) { + return scanJSXStringLiteral(); } return scanStringLiteral(); } - if (state.inXJSTag && isXJSIdentifierStart(ch)) { - return scanXJSIdentifier(); + if (state.inJSXTag && isJSXIdentifierStart(ch)) { + return scanJSXIdentifier(); } if (ch === 96) { @@ -3596,6 +4073,7 @@ parseYieldExpression: true, parseAwaitExpression: true var adv, pos, line, start, result; // If we are collecting the tokens, don't grab the next one yet. + /* istanbul ignore next */ adv = (typeof extra.advance === 'function') ? extra.advance : advance; pos = index; @@ -3603,6 +4081,7 @@ parseYieldExpression: true, parseAwaitExpression: true start = lineStart; // Scan for the next immediate token. + /* istanbul ignore if */ if (lookahead === null) { lookahead = adv(); } @@ -3648,6 +4127,7 @@ parseYieldExpression: true, parseAwaitExpression: true last = bottomRight[bottomRight.length - 1]; if (node.type === Syntax.Program) { + /* istanbul ignore else */ if (node.body.length > 0) { return; } @@ -3917,6 +4397,14 @@ parseYieldExpression: true, parseAwaitExpression: true }; }, + createTypeCast: function (expression, typeAnnotation) { + return { + type: Syntax.TypeCastExpression, + expression: expression, + typeAnnotation: typeAnnotation + }; + }, + createFunctionTypeAnnotation: function (params, returnType, rest, typeParameters) { return { type: Syntax.FunctionTypeAnnotation, @@ -4132,78 +4620,78 @@ parseYieldExpression: true, parseAwaitExpression: true }; }, - createXJSAttribute: function (name, value) { + createJSXAttribute: function (name, value) { return { - type: Syntax.XJSAttribute, + type: Syntax.JSXAttribute, name: name, value: value || null }; }, - createXJSSpreadAttribute: function (argument) { + createJSXSpreadAttribute: function (argument) { return { - type: Syntax.XJSSpreadAttribute, + type: Syntax.JSXSpreadAttribute, argument: argument }; }, - createXJSIdentifier: function (name) { + createJSXIdentifier: function (name) { return { - type: Syntax.XJSIdentifier, + type: Syntax.JSXIdentifier, name: name }; }, - createXJSNamespacedName: function (namespace, name) { + createJSXNamespacedName: function (namespace, name) { return { - type: Syntax.XJSNamespacedName, + type: Syntax.JSXNamespacedName, namespace: namespace, name: name }; }, - createXJSMemberExpression: function (object, property) { + createJSXMemberExpression: function (object, property) { return { - type: Syntax.XJSMemberExpression, + type: Syntax.JSXMemberExpression, object: object, property: property }; }, - createXJSElement: function (openingElement, closingElement, children) { + createJSXElement: function (openingElement, closingElement, children) { return { - type: Syntax.XJSElement, + type: Syntax.JSXElement, openingElement: openingElement, closingElement: closingElement, children: children }; }, - createXJSEmptyExpression: function () { + createJSXEmptyExpression: function () { return { - type: Syntax.XJSEmptyExpression + type: Syntax.JSXEmptyExpression }; }, - createXJSExpressionContainer: function (expression) { + createJSXExpressionContainer: function (expression) { return { - type: Syntax.XJSExpressionContainer, + type: Syntax.JSXExpressionContainer, expression: expression }; }, - createXJSOpeningElement: function (name, attributes, selfClosing) { + createJSXOpeningElement: function (name, attributes, selfClosing) { return { - type: Syntax.XJSOpeningElement, + type: Syntax.JSXOpeningElement, name: name, selfClosing: selfClosing, attributes: attributes }; }, - createXJSClosingElement: function (name) { + createJSXClosingElement: function (name) { return { - type: Syntax.XJSClosingElement, + type: Syntax.JSXClosingElement, name: name }; }, @@ -4448,13 +4936,14 @@ parseYieldExpression: true, parseAwaitExpression: true return arrowExpr; }, - createMethodDefinition: function (propertyType, kind, key, value) { + createMethodDefinition: function (propertyType, kind, key, value, computed) { return { type: Syntax.MethodDefinition, key: key, value: value, kind: kind, - 'static': propertyType === ClassPropertyType["static"] + 'static': propertyType === ClassPropertyType["static"], + computed: computed }; }, @@ -4543,13 +5032,13 @@ parseYieldExpression: true, parseAwaitExpression: true }; }, - createExportDeclaration: function (isDefault, declaration, specifiers, source) { + createExportDeclaration: function (isDefault, declaration, specifiers, src) { return { type: Syntax.ExportDeclaration, 'default': !!isDefault, declaration: declaration, specifiers: specifiers, - source: source + source: src }; }, @@ -4561,19 +5050,20 @@ parseYieldExpression: true, parseAwaitExpression: true }; }, - createImportDeclaration: function (specifiers, source) { + createImportDeclaration: function (specifiers, src, isType) { return { type: Syntax.ImportDeclaration, specifiers: specifiers, - source: source + source: src, + isType: isType }; }, - createYieldExpression: function (argument, delegate) { + createYieldExpression: function (argument, dlg) { return { type: Syntax.YieldExpression, argument: argument, - delegate: delegate + delegate: dlg }; }, @@ -4619,9 +5109,9 @@ parseYieldExpression: true, parseAwaitExpression: true args = Array.prototype.slice.call(arguments, 2), msg = messageFormat.replace( /%(\d)/g, - function (whole, index) { - assert(index < args.length, 'Message reference must be in range'); - return args[index]; + function (whole, idx) { + assert(idx < args.length, 'Message reference must be in range'); + return args[idx]; } ); @@ -4665,7 +5155,7 @@ parseYieldExpression: true, parseAwaitExpression: true throwError(token, Messages.UnexpectedNumber); } - if (token.type === Token.StringLiteral || token.type === Token.XJSText) { + if (token.type === Token.StringLiteral || token.type === Token.JSXText) { throwError(token, Messages.UnexpectedString); } @@ -4828,7 +5318,7 @@ parseYieldExpression: true, parseAwaitExpression: true // 11.1.4 Array Initialiser function parseArrayInitialiser() { - var elements = [], blocks = [], filter = null, tmp, possiblecomprehension = true, body, + var elements = [], blocks = [], filter = null, tmp, possiblecomprehension = true, marker = markerCreate(); expect('['); @@ -4984,11 +5474,11 @@ parseYieldExpression: true, parseAwaitExpression: true } function parseObjectProperty() { - var token, key, id, value, param, expr, computed, - marker = markerCreate(), returnType; + var token, key, id, param, computed, + marker = markerCreate(), returnType, typeParameters; token = lookahead; - computed = (token.value === '['); + computed = (token.value === '[' && token.type === Token.Punctuator); if (token.type === Token.Identifier || computed || matchAsync()) { id = parseObjectPropertyKey(); @@ -5009,7 +5499,10 @@ parseYieldExpression: true, parseAwaitExpression: true ); } - if (match('(')) { + if (match('(') || match('<')) { + if (match('<')) { + typeParameters = parseTypeParameterDeclaration(); + } return markerApply( marker, delegate.createProperty( @@ -5017,7 +5510,8 @@ parseYieldExpression: true, parseAwaitExpression: true id, parsePropertyMethodFunction({ generator: false, - async: false + async: false, + typeParameters: typeParameters }), true, false, @@ -5090,6 +5584,10 @@ parseYieldExpression: true, parseAwaitExpression: true computed = (lookahead.value === '['); key = parseObjectPropertyKey(); + if (match('<')) { + typeParameters = parseTypeParameterDeclaration(); + } + return markerApply( marker, delegate.createProperty( @@ -5097,7 +5595,8 @@ parseYieldExpression: true, parseAwaitExpression: true key, parsePropertyMethodFunction({ generator: false, - async: true + async: true, + typeParameters: typeParameters }), true, false, @@ -5127,19 +5626,46 @@ parseYieldExpression: true, parseAwaitExpression: true id = parseObjectPropertyKey(); + if (match('<')) { + typeParameters = parseTypeParameterDeclaration(); + } + if (!match('(')) { throwUnexpected(lex()); } - return markerApply(marker, delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: true }), true, false, computed)); + return markerApply(marker, delegate.createProperty( + 'init', + id, + parsePropertyMethodFunction({ + generator: true, + typeParameters: typeParameters + }), + true, + false, + computed + )); } key = parseObjectPropertyKey(); if (match(':')) { lex(); return markerApply(marker, delegate.createProperty('init', key, parseAssignmentExpression(), false, false, false)); } - if (match('(')) { - return markerApply(marker, delegate.createProperty('init', key, parsePropertyMethodFunction({ generator: false }), true, false, false)); + if (match('(') || match('<')) { + if (match('<')) { + typeParameters = parseTypeParameterDeclaration(); + } + return markerApply(marker, delegate.createProperty( + 'init', + key, + parsePropertyMethodFunction({ + generator: false, + typeParameters: typeParameters + }), + true, + false, + false + )); } throwUnexpected(lex()); } @@ -5150,9 +5676,17 @@ parseYieldExpression: true, parseAwaitExpression: true return markerApply(marker, delegate.createSpreadProperty(parseAssignmentExpression())); } + function getFieldName(key) { + var toString = String; + if (key.type === Syntax.Identifier) { + return key.name; + } + return toString(key.value); + } + function parseObjectInitialiser() { - var properties = [], property, name, key, kind, map = {}, toString = String, - marker = markerCreate(); + var properties = [], property, name, kind, storedKind, map = new StringMap(), + marker = markerCreate(), toString = String; expect('{'); @@ -5169,9 +5703,9 @@ parseYieldExpression: true, parseAwaitExpression: true } kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set; - key = '$' + name; - if (Object.prototype.hasOwnProperty.call(map, key)) { - if (map[key] === PropertyKind.Data) { + if (map.has(name)) { + storedKind = map.get(name); + if (storedKind === PropertyKind.Data) { if (strict && kind === PropertyKind.Data) { throwErrorTolerant({}, Messages.StrictDuplicateProperty); } else if (kind !== PropertyKind.Data) { @@ -5180,13 +5714,13 @@ parseYieldExpression: true, parseAwaitExpression: true } else { if (kind === PropertyKind.Data) { throwErrorTolerant({}, Messages.AccessorDataProperty); - } else if (map[key] & kind) { + } else if (storedKind & kind) { throwErrorTolerant({}, Messages.AccessorGetSet); } } - map[key] |= kind; + map.set(name, storedKind | kind); } else { - map[key] = kind; + map.set(name, kind); } } @@ -5230,14 +5764,24 @@ parseYieldExpression: true, parseAwaitExpression: true // 11.1.6 The Grouping Operator function parseGroupExpression() { - var expr; + var expr, marker, typeAnnotation; expect('('); ++state.parenthesizedCount; + marker = markerCreate(); + expr = parseExpression(); + if (match(':')) { + typeAnnotation = parseTypeAnnotation(); + expr = markerApply(marker, delegate.createTypeCast( + expr, + typeAnnotation + )); + } + expect(')'); return expr; @@ -5326,7 +5870,9 @@ parseYieldExpression: true, parseAwaitExpression: true if (match('/') || match('/=')) { marker = markerCreate(); - return markerApply(marker, delegate.createLiteral(scanRegExp())); + expr = delegate.createLiteral(scanRegExp()); + peek(); + return markerApply(marker, expr); } if (type === Token.Template) { @@ -5334,7 +5880,7 @@ parseYieldExpression: true, parseAwaitExpression: true } if (match('<')) { - return parseXJSElement(); + return parseJSXElement(); } throwUnexpected(lex()); @@ -5694,6 +6240,8 @@ parseYieldExpression: true, parseAwaitExpression: true // 11.13 Assignment Operators + // 12.14.5 AssignmentPattern + function reinterpretAsAssignmentBindingPattern(expr) { var i, len, property, element; @@ -5717,6 +6265,7 @@ parseYieldExpression: true, parseAwaitExpression: true expr.type = Syntax.ArrayPattern; for (i = 0, len = expr.elements.length; i < len; i += 1) { element = expr.elements[i]; + /* istanbul ignore else */ if (element) { reinterpretAsAssignmentBindingPattern(element); } @@ -5731,12 +6280,14 @@ parseYieldExpression: true, parseAwaitExpression: true throwError({}, Messages.ObjectPatternAsSpread); } } else { + /* istanbul ignore else */ if (expr.type !== Syntax.MemberExpression && expr.type !== Syntax.CallExpression && expr.type !== Syntax.NewExpression) { throwError({}, Messages.InvalidLHSInAssignment); } } } + // 13.2.3 BindingPattern function reinterpretAsDestructuredParameter(options, expr) { var i, len, property, element; @@ -5767,10 +6318,14 @@ parseYieldExpression: true, parseAwaitExpression: true } } else if (expr.type === Syntax.Identifier) { validateParam(options, expr, expr.name); - } else { - if (expr.type !== Syntax.MemberExpression) { + } else if (expr.type === Syntax.SpreadElement) { + // BindingRestElement only allows BindingIdentifier + if (expr.argument.type !== Syntax.Identifier) { throwError({}, Messages.InvalidLHSInFormalsList); } + validateParam(options, expr.argument, expr.argument.name); + } else { + throwError({}, Messages.InvalidLHSInFormalsList); } } @@ -5782,7 +6337,7 @@ parseYieldExpression: true, parseAwaitExpression: true defaultCount = 0; rest = null; options = { - paramSet: {} + paramSet: new StringMap() }; for (i = 0, len = expressions.length; i < len; i += 1) { @@ -5797,6 +6352,9 @@ parseYieldExpression: true, parseAwaitExpression: true defaults.push(null); } else if (param.type === Syntax.SpreadElement) { assert(i === len - 1, 'It is guaranteed that SpreadElement is last element by parseExpression'); + if (param.argument.type !== Syntax.Identifier) { + throwError({}, Messages.InvalidLHSInFormalsList); + } reinterpretAsDestructuredParameter(options, param.argument); rest = param.argument; } else if (param.type === Syntax.AssignmentExpression) { @@ -5865,7 +6423,8 @@ parseYieldExpression: true, parseAwaitExpression: true function parseAssignmentExpression() { var marker, expr, token, params, oldParenthesizedCount, - backtrackToken = lookahead, possiblyAsync = false; + startsWithParen = false, backtrackToken = lookahead, + possiblyAsync = false; if (matchYield()) { return parseYieldExpression(); @@ -5902,6 +6461,7 @@ parseYieldExpression: true, parseAwaitExpression: true params.async = possiblyAsync; return parseArrowFunctionExpression(params, marker); } + startsWithParen = true; } token = lookahead; @@ -5921,6 +6481,13 @@ parseYieldExpression: true, parseAwaitExpression: true state.parenthesizedCount === (oldParenthesizedCount + 1))) { if (expr.type === Syntax.Identifier) { params = reinterpretAsCoverFormalsList([ expr ]); + } else if (expr.type === Syntax.AssignmentExpression || + expr.type === Syntax.ArrayExpression || + expr.type === Syntax.ObjectExpression) { + if (!startsWithParen) { + throwUnexpected(lex()); + } + params = reinterpretAsCoverFormalsList([ expr ]); } else if (expr.type === Syntax.SequenceExpression) { params = reinterpretAsCoverFormalsList(expr.expressions); } @@ -5961,9 +6528,7 @@ parseYieldExpression: true, parseAwaitExpression: true // 11.14 Comma Operator function parseExpression() { - var marker, expr, expressions, sequence, coverFormalsList, spreadFound, oldParenthesizedCount; - - oldParenthesizedCount = state.parenthesizedCount; + var marker, expr, expressions, sequence, spreadFound; marker = markerCreate(); expr = parseAssignmentExpression(); @@ -5991,18 +6556,6 @@ parseYieldExpression: true, parseAwaitExpression: true sequence = markerApply(marker, delegate.createSequenceExpression(expressions)); } - if (match('=>')) { - // Do not allow nested parentheses on the LHS of the =>. - if (state.parenthesizedCount === oldParenthesizedCount || state.parenthesizedCount === (oldParenthesizedCount + 1)) { - expr = expr.type === Syntax.SequenceExpression ? expr.expressions : expressions; - coverFormalsList = reinterpretAsCoverFormalsList(expr); - if (coverFormalsList) { - return parseArrowFunctionExpression(coverFormalsList, marker); - } - } - throwUnexpected(lex()); - } - if (spreadFound && lookahead2().value !== '=>') { throwError({}, Messages.IllegalSpread); } @@ -6049,7 +6602,7 @@ parseYieldExpression: true, parseAwaitExpression: true expect('<'); while (!match('>')) { - paramTypes.push(parseVariableIdentifier()); + paramTypes.push(parseTypeAnnotatableIdentifier()); if (!match('>')) { expect(','); } @@ -6153,14 +6706,19 @@ parseYieldExpression: true, parseAwaitExpression: true function parseObjectType(allowStatic) { var callProperties = [], indexers = [], marker, optional = false, - properties = [], property, propertyKey, propertyTypeAnnotation, - token, isStatic; + properties = [], propertyKey, propertyTypeAnnotation, + token, isStatic, matchStatic; expect('{'); while (!match('}')) { marker = markerCreate(); - if (allowStatic && matchContextualKeyword('static')) { + matchStatic = + strict + ? matchKeyword('static') + : matchContextualKeyword('static'); + + if (allowStatic && matchStatic) { token = lex(); isStatic = true; } @@ -6212,9 +6770,8 @@ parseYieldExpression: true, parseAwaitExpression: true } function parseGenericType() { - var marker = markerCreate(), returnType = null, - typeParameters = null, typeIdentifier, - typeIdentifierMarker = markerCreate; + var marker = markerCreate(), + typeParameters = null, typeIdentifier; typeIdentifier = parseVariableIdentifier(); @@ -6304,7 +6861,7 @@ parseYieldExpression: true, parseAwaitExpression: true // 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, + var params = null, returnType = null, marker = markerCreate(), rest = null, tmp, typeParameters, token, type, isGroupedType = false; @@ -6540,6 +7097,7 @@ parseYieldExpression: true, parseAwaitExpression: true markerApply(typeAnnotationMarker, id); } } else { + /* istanbul ignore next */ id = state.allowKeyword ? parseNonComputedProperty() : parseTypeAnnotatableIdentifier(); // 12.2.1 if (strict && isRestrictedWord(id.name)) { @@ -6549,7 +7107,7 @@ parseYieldExpression: true, parseAwaitExpression: true if (kind === 'const') { if (!match('=')) { - throwError({}, Messages.NoUnintializedConst); + throwError({}, Messages.NoUninitializedConst); } expect('='); init = parseAssignmentExpression(); @@ -6641,7 +7199,8 @@ parseYieldExpression: true, parseAwaitExpression: true } function parseExportDeclaration() { - var backtrackToken, id, previousAllowKeyword, declaration = null, + var declaration = null, + possibleIdentifierToken, sourceElement, isExportFromIdentifier, src = null, specifiers = [], marker = markerCreate(); @@ -6653,20 +7212,17 @@ parseYieldExpression: true, parseAwaitExpression: true // export default ... lex(); if (matchKeyword('function') || matchKeyword('class')) { - backtrackToken = lookahead; - lex(); - if (isIdentifierName(lookahead)) { + possibleIdentifierToken = lookahead2(); + if (isIdentifierName(possibleIdentifierToken)) { // covers: // export default function foo () {} // export default class foo {} - id = parseNonComputedProperty(); - rewind(backtrackToken); - return markerApply(marker, delegate.createExportDeclaration(true, parseSourceElement(), [id], null)); + sourceElement = parseSourceElement(); + return markerApply(marker, delegate.createExportDeclaration(true, sourceElement, [sourceElement.id], null)); } // covers: // export default function () {} // export default class {} - rewind(backtrackToken); switch (lookahead.value) { case 'class': return markerApply(marker, delegate.createExportDeclaration(true, parseClassExpression(), [], null)); @@ -6694,10 +7250,11 @@ parseYieldExpression: true, parseAwaitExpression: true } // non-default export - if (lookahead.type === Token.Keyword) { + if (lookahead.type === Token.Keyword || matchContextualKeyword('type')) { // covers: // export var f = 1; switch (lookahead.value) { + case 'type': case 'let': case 'const': case 'var': @@ -6724,10 +7281,12 @@ parseYieldExpression: true, parseAwaitExpression: true } expect('{'); - do { - isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default'); - specifiers.push(parseExportSpecifier()); - } while (match(',') && lex()); + if (!match('}')) { + do { + isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default'); + specifiers.push(parseExportSpecifier()); + } while (match(',') && lex()); + } expect('}'); if (matchContextualKeyword('from')) { @@ -6768,9 +7327,11 @@ parseYieldExpression: true, parseAwaitExpression: true var specifiers = []; // {foo, bar as bas} expect('{'); - do { - specifiers.push(parseImportSpecifier()); - } while (match(',') && lex()); + if (!match('}')) { + do { + specifiers.push(parseImportSpecifier()); + } while (match(',') && lex()); + } expect('}'); return specifiers; } @@ -6799,9 +7360,20 @@ parseYieldExpression: true, parseAwaitExpression: true } function parseImportDeclaration() { - var specifiers, src, marker = markerCreate(); + var specifiers, src, marker = markerCreate(), isType = false, token2; expectKeyword('import'); + + if (matchContextualKeyword('type')) { + token2 = lookahead2(); + if ((token2.type === Token.Identifier && token2.value !== 'from') || + (token2.type === Token.Punctuator && + (token2.value === '{' || token2.value === '*'))) { + isType = true; + lex(); + } + } + specifiers = []; if (lookahead.type === Token.StringLiteral) { @@ -6809,7 +7381,7 @@ parseYieldExpression: true, parseAwaitExpression: true // import "foo"; src = parseModuleSpecifier(); consumeSemicolon(); - return markerApply(marker, delegate.createImportDeclaration(specifiers, src)); + return markerApply(marker, delegate.createImportDeclaration(specifiers, src, isType)); } if (!matchKeyword('default') && isIdentifierName(lookahead)) { @@ -6841,7 +7413,7 @@ parseYieldExpression: true, parseAwaitExpression: true src = parseModuleSpecifier(); consumeSemicolon(); - return markerApply(marker, delegate.createImportDeclaration(specifiers, src)); + return markerApply(marker, delegate.createImportDeclaration(specifiers, src, isType)); } // 12.3 Empty Statement @@ -7038,7 +7610,7 @@ parseYieldExpression: true, parseAwaitExpression: true // 12.7 The continue statement function parseContinueStatement() { - var label = null, key, marker = markerCreate(); + var label = null, marker = markerCreate(); expectKeyword('continue'); @@ -7064,8 +7636,7 @@ parseYieldExpression: true, parseAwaitExpression: true if (lookahead.type === Token.Identifier) { label = parseVariableIdentifier(); - key = '$' + label.name; - if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + if (!state.labelSet.has(label.name)) { throwError({}, Messages.UnknownLabel, label.name); } } @@ -7082,7 +7653,7 @@ parseYieldExpression: true, parseAwaitExpression: true // 12.8 The break statement function parseBreakStatement() { - var label = null, key, marker = markerCreate(); + var label = null, marker = markerCreate(); expectKeyword('break'); @@ -7108,8 +7679,7 @@ parseYieldExpression: true, parseAwaitExpression: true if (lookahead.type === Token.Identifier) { label = parseVariableIdentifier(); - key = '$' + label.name; - if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + if (!state.labelSet.has(label.name)) { throwError({}, Messages.UnknownLabel, label.name); } } @@ -7337,8 +7907,7 @@ parseYieldExpression: true, parseAwaitExpression: true var type = lookahead.type, marker, expr, - labeledBody, - key; + labeledBody; if (type === Token.EOF) { throwUnexpected(lookahead); @@ -7405,14 +7974,13 @@ parseYieldExpression: true, parseAwaitExpression: true if ((expr.type === Syntax.Identifier) && match(':')) { lex(); - key = '$' + expr.name; - if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + if (state.labelSet.has(expr.name)) { throwError({}, Messages.Redeclaration, 'Label', expr.name); } - state.labelSet[key] = true; + state.labelSet.set(expr.name, true); labeledBody = parseStatement(); - delete state.labelSet[key]; + state.labelSet["delete"](expr.name); return markerApply(marker, delegate.createLabeledStatement(expr, labeledBody)); } @@ -7468,7 +8036,7 @@ parseYieldExpression: true, parseAwaitExpression: true oldInFunctionBody = state.inFunctionBody; oldParenthesizedCount = state.parenthesizedCount; - state.labelSet = {}; + state.labelSet = new StringMap(); state.inIteration = false; state.inSwitch = false; state.inFunctionBody = true; @@ -7497,13 +8065,12 @@ parseYieldExpression: true, parseAwaitExpression: true } function validateParam(options, param, name) { - var key = '$' + name; if (strict) { if (isRestrictedWord(name)) { options.stricted = param; options.message = Messages.StrictParamName; } - if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + if (options.paramSet.has(name)) { options.stricted = param; options.message = Messages.StrictParamDupe; } @@ -7514,12 +8081,12 @@ parseYieldExpression: true, parseAwaitExpression: true } else if (isStrictModeReservedWord(name)) { options.firstRestricted = param; options.message = Messages.StrictReservedWord; - } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + } else if (options.paramSet.has(name)) { options.firstRestricted = param; options.message = Messages.StrictParamDupe; } } - options.paramSet[key] = true; + options.paramSet.set(name, true); } function parseParam(options) { @@ -7601,7 +8168,7 @@ parseYieldExpression: true, parseAwaitExpression: true expect('('); if (!match(')')) { - options.paramSet = {}; + options.paramSet = new StringMap(); while (index < length) { if (!parseParam(options)) { break; @@ -7814,12 +8381,22 @@ parseYieldExpression: true, parseAwaitExpression: true return markerApply(marker, delegate.createAwaitExpression(expr)); } - // 14 Classes + // 14 Functions and classes + + // 14.1 Functions is defined above (13 in ES5) + // 14.2 Arrow Functions Definitions is defined in (7.3 assignments) - function parseMethodDefinition(existingPropNames, key, isStatic, generator, computed) { - var token, param, propType, isValidDuplicateProp = false, - isAsync, typeParameters, tokenValue, returnType, - annotationMarker; + // 14.3 Method Definitions + // 14.3.7 + function specialMethod(methodDefinition) { + return methodDefinition.kind === 'get' || + methodDefinition.kind === 'set' || + methodDefinition.value.generator; + } + + function parseMethodDefinition(key, isStatic, generator, computed) { + var token, param, propType, + isAsync, typeParameters, tokenValue, returnType; propType = isStatic ? ClassPropertyType["static"] : ClassPropertyType.prototype; @@ -7828,7 +8405,8 @@ parseYieldExpression: true, parseAwaitExpression: true propType, '', key, - parsePropertyMethodFunction({ generator: true }) + parsePropertyMethodFunction({ generator: true }), + computed ); } @@ -7837,24 +8415,6 @@ parseYieldExpression: true, parseAwaitExpression: true if (tokenValue === 'get' && !match('(')) { key = parseObjectPropertyKey(); - // It is a syntax error if any other properties have a name - // duplicating this one unless they are a setter - if (existingPropNames[propType].hasOwnProperty(key.name)) { - isValidDuplicateProp = - // There isn't already a getter for this prop - existingPropNames[propType][key.name].get === undefined - // There isn't already a data prop by this name - && existingPropNames[propType][key.name].data === undefined - // The only existing prop by this name is a setter - && existingPropNames[propType][key.name].set !== undefined; - if (!isValidDuplicateProp) { - throwError(key, Messages.IllegalDuplicateClassProperty); - } - } else { - existingPropNames[propType][key.name] = {}; - } - existingPropNames[propType][key.name].get = true; - expect('('); expect(')'); if (match(':')) { @@ -7864,30 +8424,13 @@ parseYieldExpression: true, parseAwaitExpression: true propType, 'get', key, - parsePropertyFunction({ generator: false, returnType: returnType }) + parsePropertyFunction({ generator: false, returnType: returnType }), + computed ); } if (tokenValue === 'set' && !match('(')) { key = parseObjectPropertyKey(); - // It is a syntax error if any other properties have a name - // duplicating this one unless they are a getter - if (existingPropNames[propType].hasOwnProperty(key.name)) { - isValidDuplicateProp = - // There isn't already a setter for this prop - existingPropNames[propType][key.name].set === undefined - // There isn't already a data prop by this name - && existingPropNames[propType][key.name].data === undefined - // The only existing prop by this name is a getter - && existingPropNames[propType][key.name].get !== undefined; - if (!isValidDuplicateProp) { - throwError(key, Messages.IllegalDuplicateClassProperty); - } - } else { - existingPropNames[propType][key.name] = {}; - } - existingPropNames[propType][key.name].set = true; - expect('('); token = lookahead; param = [ parseTypeAnnotatableIdentifier() ]; @@ -7904,7 +8447,8 @@ parseYieldExpression: true, parseAwaitExpression: true generator: false, name: token, returnType: returnType - }) + }), + computed ); } @@ -7917,15 +8461,6 @@ parseYieldExpression: true, parseAwaitExpression: true key = parseObjectPropertyKey(); } - // It is a syntax error if any other properties have the same name as a - // non-getter, non-setter method - if (existingPropNames[propType].hasOwnProperty(key.name)) { - throwError(key, Messages.IllegalDuplicateClassProperty); - } else { - existingPropNames[propType][key.name] = {}; - } - existingPropNames[propType][key.name].data = true; - return delegate.createMethodDefinition( propType, '', @@ -7934,11 +8469,12 @@ parseYieldExpression: true, parseAwaitExpression: true generator: false, async: isAsync, typeParameters: typeParameters - }) + }), + computed ); } - function parseClassProperty(existingPropNames, key, computed, isStatic) { + function parseClassProperty(key, computed, isStatic) { var typeAnnotation; typeAnnotation = parseTypeAnnotation(); @@ -7952,12 +8488,12 @@ parseYieldExpression: true, parseAwaitExpression: true ); } - function parseClassElement(existingProps) { - var computed, generator = false, key, marker = markerCreate(), - isStatic = false; + function parseClassElement() { + var computed = false, generator = false, key, marker = markerCreate(), + isStatic = false, possiblyOpenBracketToken; if (match(';')) { lex(); - return; + return undefined; } if (lookahead.value === 'static') { @@ -7970,15 +8506,23 @@ parseYieldExpression: true, parseAwaitExpression: true generator = true; } - computed = (lookahead.value === '['); + possiblyOpenBracketToken = lookahead; + if (matchContextualKeyword('get') || matchContextualKeyword('set')) { + possiblyOpenBracketToken = lookahead2(); + } + + if (possiblyOpenBracketToken.type === Token.Punctuator + && possiblyOpenBracketToken.value === '[') { + computed = true; + } + key = parseObjectPropertyKey(); if (!generator && lookahead.value === ':') { - return markerApply(marker, parseClassProperty(existingProps, key, computed, isStatic)); + return markerApply(marker, parseClassProperty(key, computed, isStatic)); } return markerApply(marker, parseMethodDefinition( - existingProps, key, isStatic, generator, @@ -7987,10 +8531,11 @@ parseYieldExpression: true, parseAwaitExpression: true } function parseClassBody() { - var classElement, classElements = [], existingProps = {}, marker = markerCreate(); + var classElement, classElements = [], existingProps = {}, + marker = markerCreate(), propName, propType; - existingProps[ClassPropertyType["static"]] = {}; - existingProps[ClassPropertyType.prototype] = {}; + existingProps[ClassPropertyType["static"]] = new StringMap(); + existingProps[ClassPropertyType.prototype] = new StringMap(); expect('{'); @@ -8002,6 +8547,25 @@ parseYieldExpression: true, parseAwaitExpression: true if (typeof classElement !== 'undefined') { classElements.push(classElement); + + propName = !classElement.computed && getFieldName(classElement.key); + if (propName !== false) { + propType = classElement["static"] ? + ClassPropertyType["static"] : + ClassPropertyType.prototype; + + if (classElement.type === Syntax.MethodDefinition) { + if (propName === 'constructor' && !classElement["static"]) { + if (specialMethod(classElement)) { + throwError(classElement, Messages.IllegalClassConstructorProperty); + } + if (existingProps[ClassPropertyType.prototype].has('constructor')) { + throwError(classElement.key, Messages.IllegalDuplicateClassProperty); + } + } + existingProps[propType].set(propName, true); + } + } } } @@ -8012,7 +8576,11 @@ parseYieldExpression: true, parseAwaitExpression: true function parseClassImplements() { var id, implemented = [], marker, typeParameters; - expectContextualKeyword('implements'); + if (strict) { + expectKeyword('implements'); + } else { + expectContextualKeyword('implements'); + } while (index < length) { marker = markerCreate(); id = parseVariableIdentifier(); @@ -8035,11 +8603,17 @@ parseYieldExpression: true, parseAwaitExpression: true function parseClassExpression() { var id, implemented, previousYieldAllowed, superClass = null, - superTypeParameters, marker = markerCreate(), typeParameters; + superTypeParameters, marker = markerCreate(), typeParameters, + matchImplements; expectKeyword('class'); - if (!matchKeyword('extends') && !matchContextualKeyword('implements') && !match('{')) { + matchImplements = + strict + ? matchKeyword('implements') + : matchContextualKeyword('implements'); + + if (!matchKeyword('extends') && !matchImplements && !match('{')) { id = parseVariableIdentifier(); } @@ -8058,7 +8632,7 @@ parseYieldExpression: true, parseAwaitExpression: true state.yieldAllowed = previousYieldAllowed; } - if (matchContextualKeyword('implements')) { + if (strict ? matchKeyword('implements') : matchContextualKeyword('implements')) { implemented = parseClassImplements(); } @@ -8095,7 +8669,7 @@ parseYieldExpression: true, parseAwaitExpression: true state.yieldAllowed = previousYieldAllowed; } - if (matchContextualKeyword('implements')) { + if (strict ? matchKeyword('implements') : matchContextualKeyword('implements')) { implemented = parseClassImplements(); } @@ -8120,6 +8694,17 @@ parseYieldExpression: true, parseAwaitExpression: true return parseConstLetDeclaration(lookahead.value); case 'function': return parseFunctionDeclaration(); + case 'export': + throwErrorTolerant({}, Messages.IllegalExportDeclaration); + return parseExportDeclaration(); + case 'import': + throwErrorTolerant({}, Messages.IllegalImportDeclaration); + return parseImportDeclaration(); + case 'interface': + if (lookahead2().type === Token.Identifier) { + return parseInterface(); + } + return parseStatement(); default: return parseStatement(); } @@ -8158,7 +8743,9 @@ parseYieldExpression: true, parseAwaitExpression: true } function parseProgramElement() { - if (lookahead.type === Token.Keyword) { + var isModule = extra.sourceType === 'module' || extra.sourceType === 'nonStrictModule'; + + if (isModule && lookahead.type === Token.Keyword) { switch (lookahead.value) { case 'export': return parseExportDeclaration(); @@ -8210,170 +8797,13 @@ parseYieldExpression: true, parseAwaitExpression: true function parseProgram() { var body, marker = markerCreate(); - strict = false; + strict = extra.sourceType === 'module'; peek(); body = parseProgramElements(); return markerApply(marker, delegate.createProgram(body)); } - // The following functions are needed only when the option to preserve - // the comments is active. - - function addComment(type, value, start, end, loc) { - var comment; - - assert(typeof start === 'number', 'Comment must have valid position'); - - // Because the way the actual token is scanned, often the comments - // (if any) are skipped twice during the lexical analysis. - // Thus, we need to skip adding a comment if the comment array already - // handled it. - if (state.lastCommentStart >= start) { - return; - } - state.lastCommentStart = start; - - comment = { - type: type, - value: value - }; - if (extra.range) { - comment.range = [start, end]; - } - if (extra.loc) { - comment.loc = loc; - } - extra.comments.push(comment); - if (extra.attachComment) { - extra.leadingComments.push(comment); - extra.trailingComments.push(comment); - } - } - - function scanComment() { - var comment, ch, loc, start, blockComment, lineComment; - - comment = ''; - blockComment = false; - lineComment = false; - - while (index < length) { - ch = source.charAt(index); - - if (lineComment) { - ch = source.charAt(index++); - if (isLineTerminator(ch.charCodeAt(0))) { - loc.end = { - line: lineNumber, - column: index - lineStart - 1 - }; - lineComment = false; - addComment('Line', comment, start, index - 1, loc); - if (ch === '\r' && source.charAt(index) === '\n') { - ++index; - } - ++lineNumber; - lineStart = index; - comment = ''; - } else if (index >= length) { - lineComment = false; - comment += ch; - loc.end = { - line: lineNumber, - column: length - lineStart - }; - addComment('Line', comment, start, length, loc); - } else { - comment += ch; - } - } else if (blockComment) { - if (isLineTerminator(ch.charCodeAt(0))) { - if (ch === '\r') { - ++index; - comment += '\r'; - } - if (ch !== '\r' || source.charAt(index) === '\n') { - comment += source.charAt(index); - ++lineNumber; - ++index; - lineStart = index; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } - } else { - ch = source.charAt(index++); - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - comment += ch; - if (ch === '*') { - ch = source.charAt(index); - if (ch === '/') { - comment = comment.substr(0, comment.length - 1); - blockComment = false; - ++index; - loc.end = { - line: lineNumber, - column: index - lineStart - }; - addComment('Block', comment, start, index, loc); - comment = ''; - } - } - } - } else if (ch === '/') { - ch = source.charAt(index + 1); - if (ch === '/') { - loc = { - start: { - line: lineNumber, - column: index - lineStart - } - }; - start = index; - index += 2; - lineComment = true; - if (index >= length) { - loc.end = { - line: lineNumber, - column: index - lineStart - }; - lineComment = false; - addComment('Line', comment, start, index, loc); - } - } else if (ch === '*') { - start = index; - index += 2; - blockComment = true; - loc = { - start: { - line: lineNumber, - column: index - lineStart - 2 - } - }; - if (index >= length) { - throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); - } - } else { - break; - } - } else if (isWhiteSpace(ch.charCodeAt(0))) { - ++index; - } else if (isLineTerminator(ch.charCodeAt(0))) { - ++index; - if (ch === '\r' && source.charAt(index) === '\n') { - ++index; - } - ++lineNumber; - lineStart = index; - } else { - break; - } - } - } - - // 16 XJS + // 16 JSX XHTMLEntities = { quot: '\u0022', @@ -8631,45 +9061,48 @@ parseYieldExpression: true, parseAwaitExpression: true diams: '\u2666' }; - function getQualifiedXJSName(object) { - if (object.type === Syntax.XJSIdentifier) { + function getQualifiedJSXName(object) { + if (object.type === Syntax.JSXIdentifier) { return object.name; } - if (object.type === Syntax.XJSNamespacedName) { + if (object.type === Syntax.JSXNamespacedName) { return object.namespace.name + ':' + object.name.name; } - if (object.type === Syntax.XJSMemberExpression) { + /* istanbul ignore else */ + if (object.type === Syntax.JSXMemberExpression) { return ( - getQualifiedXJSName(object.object) + '.' + - getQualifiedXJSName(object.property) + getQualifiedJSXName(object.object) + '.' + + getQualifiedJSXName(object.property) ); } + /* istanbul ignore next */ + throwUnexpected(object); } - function isXJSIdentifierStart(ch) { + function isJSXIdentifierStart(ch) { // exclude backslash (\) return (ch !== 92) && isIdentifierStart(ch); } - function isXJSIdentifierPart(ch) { + function isJSXIdentifierPart(ch) { // exclude backslash (\) and add hyphen (-) return (ch !== 92) && (ch === 45 || isIdentifierPart(ch)); } - function scanXJSIdentifier() { + function scanJSXIdentifier() { var ch, start, value = ''; start = index; while (index < length) { ch = source.charCodeAt(index); - if (!isXJSIdentifierPart(ch)) { + if (!isJSXIdentifierPart(ch)) { break; } value += source.charAt(index++); } return { - type: Token.XJSIdentifier, + type: Token.JSXIdentifier, value: value, lineNumber: lineNumber, lineStart: lineStart, @@ -8677,7 +9110,7 @@ parseYieldExpression: true, parseAwaitExpression: true }; } - function scanXJSEntity() { + function scanJSXEntity() { var ch, str = '', start = index, count = 0, code; ch = source.charAt(index); assert(ch === '&', 'Entity must start with an ampersand'); @@ -8704,6 +9137,7 @@ parseYieldExpression: true, parseAwaitExpression: true if (!isNaN(code)) { return String.fromCharCode(code); } + /* istanbul ignore else */ } else if (XHTMLEntities[str]) { return XHTMLEntities[str]; } @@ -8714,7 +9148,7 @@ parseYieldExpression: true, parseAwaitExpression: true return '&'; } - function scanXJSText(stopChars) { + function scanJSXText(stopChars) { var ch, str = '', start; start = index; while (index < length) { @@ -8723,7 +9157,7 @@ parseYieldExpression: true, parseAwaitExpression: true break; } if (ch === '&') { - str += scanXJSEntity(); + str += scanJSXEntity(); } else { index++; if (ch === '\r' && source.charAt(index) === '\n') { @@ -8739,7 +9173,7 @@ parseYieldExpression: true, parseAwaitExpression: true } } return { - type: Token.XJSText, + type: Token.JSXText, value: str, lineNumber: lineNumber, lineStart: lineStart, @@ -8747,7 +9181,7 @@ parseYieldExpression: true, parseAwaitExpression: true }; } - function scanXJSStringLiteral() { + function scanJSXStringLiteral() { var innerToken, quote, start; quote = source.charAt(index); @@ -8757,7 +9191,7 @@ parseYieldExpression: true, parseAwaitExpression: true start = index; ++index; - innerToken = scanXJSText([quote]); + innerToken = scanJSXText([quote]); if (quote !== source.charAt(index)) { throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); @@ -8771,254 +9205,256 @@ parseYieldExpression: true, parseAwaitExpression: true } /** - * Between XJS opening and closing tags (e.g. HERE), anything that - * is not another XJS tag and is not an expression wrapped by {} is text. + * Between JSX opening and closing tags (e.g. HERE), anything that + * is not another JSX tag and is not an expression wrapped by {} is text. */ - function advanceXJSChild() { + function advanceJSXChild() { var ch = source.charCodeAt(index); - // { (123) and < (60) - if (ch !== 123 && ch !== 60) { - return scanXJSText(['<', '{']); + // '<' 60, '>' 62, '{' 123, '}' 125 + if (ch !== 60 && ch !== 62 && ch !== 123 && ch !== 125) { + return scanJSXText(['<', '>', '{', '}']); } return scanPunctuator(); } - function parseXJSIdentifier() { + function parseJSXIdentifier() { var token, marker = markerCreate(); - if (lookahead.type !== Token.XJSIdentifier) { + if (lookahead.type !== Token.JSXIdentifier) { throwUnexpected(lookahead); } token = lex(); - return markerApply(marker, delegate.createXJSIdentifier(token.value)); + return markerApply(marker, delegate.createJSXIdentifier(token.value)); } - function parseXJSNamespacedName() { + function parseJSXNamespacedName() { var namespace, name, marker = markerCreate(); - namespace = parseXJSIdentifier(); + namespace = parseJSXIdentifier(); expect(':'); - name = parseXJSIdentifier(); + name = parseJSXIdentifier(); - return markerApply(marker, delegate.createXJSNamespacedName(namespace, name)); + return markerApply(marker, delegate.createJSXNamespacedName(namespace, name)); } - function parseXJSMemberExpression() { + function parseJSXMemberExpression() { var marker = markerCreate(), - expr = parseXJSIdentifier(); + expr = parseJSXIdentifier(); while (match('.')) { lex(); - expr = markerApply(marker, delegate.createXJSMemberExpression(expr, parseXJSIdentifier())); + expr = markerApply(marker, delegate.createJSXMemberExpression(expr, parseJSXIdentifier())); } return expr; } - function parseXJSElementName() { + function parseJSXElementName() { if (lookahead2().value === ':') { - return parseXJSNamespacedName(); + return parseJSXNamespacedName(); } if (lookahead2().value === '.') { - return parseXJSMemberExpression(); + return parseJSXMemberExpression(); } - return parseXJSIdentifier(); + return parseJSXIdentifier(); } - function parseXJSAttributeName() { + function parseJSXAttributeName() { if (lookahead2().value === ':') { - return parseXJSNamespacedName(); + return parseJSXNamespacedName(); } - return parseXJSIdentifier(); + return parseJSXIdentifier(); } - function parseXJSAttributeValue() { + function parseJSXAttributeValue() { var value, marker; if (match('{')) { - value = parseXJSExpressionContainer(); - if (value.expression.type === Syntax.XJSEmptyExpression) { + value = parseJSXExpressionContainer(); + if (value.expression.type === Syntax.JSXEmptyExpression) { throwError( value, - 'XJS attributes must only be assigned a non-empty ' + + 'JSX attributes must only be assigned a non-empty ' + 'expression' ); } } else if (match('<')) { - value = parseXJSElement(); - } else if (lookahead.type === Token.XJSText) { + value = parseJSXElement(); + } else if (lookahead.type === Token.JSXText) { marker = markerCreate(); value = markerApply(marker, delegate.createLiteral(lex())); } else { - throwError({}, Messages.InvalidXJSAttributeValue); + throwError({}, Messages.InvalidJSXAttributeValue); } return value; } - function parseXJSEmptyExpression() { + function parseJSXEmptyExpression() { var marker = markerCreatePreserveWhitespace(); while (source.charAt(index) !== '}') { index++; } - return markerApply(marker, delegate.createXJSEmptyExpression()); + return markerApply(marker, delegate.createJSXEmptyExpression()); } - function parseXJSExpressionContainer() { - var expression, origInXJSChild, origInXJSTag, marker = markerCreate(); + function parseJSXExpressionContainer() { + var expression, origInJSXChild, origInJSXTag, marker = markerCreate(); - origInXJSChild = state.inXJSChild; - origInXJSTag = state.inXJSTag; - state.inXJSChild = false; - state.inXJSTag = false; + origInJSXChild = state.inJSXChild; + origInJSXTag = state.inJSXTag; + state.inJSXChild = false; + state.inJSXTag = false; expect('{'); if (match('}')) { - expression = parseXJSEmptyExpression(); + expression = parseJSXEmptyExpression(); } else { expression = parseExpression(); } - state.inXJSChild = origInXJSChild; - state.inXJSTag = origInXJSTag; + state.inJSXChild = origInJSXChild; + state.inJSXTag = origInJSXTag; expect('}'); - return markerApply(marker, delegate.createXJSExpressionContainer(expression)); + return markerApply(marker, delegate.createJSXExpressionContainer(expression)); } - function parseXJSSpreadAttribute() { - var expression, origInXJSChild, origInXJSTag, marker = markerCreate(); + function parseJSXSpreadAttribute() { + var expression, origInJSXChild, origInJSXTag, marker = markerCreate(); - origInXJSChild = state.inXJSChild; - origInXJSTag = state.inXJSTag; - state.inXJSChild = false; - state.inXJSTag = false; + origInJSXChild = state.inJSXChild; + origInJSXTag = state.inJSXTag; + state.inJSXChild = false; + state.inJSXTag = false; expect('{'); expect('...'); expression = parseAssignmentExpression(); - state.inXJSChild = origInXJSChild; - state.inXJSTag = origInXJSTag; + state.inJSXChild = origInJSXChild; + state.inJSXTag = origInJSXTag; expect('}'); - return markerApply(marker, delegate.createXJSSpreadAttribute(expression)); + return markerApply(marker, delegate.createJSXSpreadAttribute(expression)); } - function parseXJSAttribute() { + function parseJSXAttribute() { var name, marker; if (match('{')) { - return parseXJSSpreadAttribute(); + return parseJSXSpreadAttribute(); } marker = markerCreate(); - name = parseXJSAttributeName(); + name = parseJSXAttributeName(); // HTML empty attribute if (match('=')) { lex(); - return markerApply(marker, delegate.createXJSAttribute(name, parseXJSAttributeValue())); + return markerApply(marker, delegate.createJSXAttribute(name, parseJSXAttributeValue())); } - return markerApply(marker, delegate.createXJSAttribute(name)); + return markerApply(marker, delegate.createJSXAttribute(name)); } - function parseXJSChild() { + function parseJSXChild() { var token, marker; if (match('{')) { - token = parseXJSExpressionContainer(); - } else if (lookahead.type === Token.XJSText) { + token = parseJSXExpressionContainer(); + } else if (lookahead.type === Token.JSXText) { marker = markerCreatePreserveWhitespace(); token = markerApply(marker, delegate.createLiteral(lex())); + } else if (match('<')) { + token = parseJSXElement(); } else { - token = parseXJSElement(); + throwUnexpected(lookahead); } return token; } - function parseXJSClosingElement() { - var name, origInXJSChild, origInXJSTag, marker = markerCreate(); - origInXJSChild = state.inXJSChild; - origInXJSTag = state.inXJSTag; - state.inXJSChild = false; - state.inXJSTag = true; + function parseJSXClosingElement() { + var name, origInJSXChild, origInJSXTag, marker = markerCreate(); + origInJSXChild = state.inJSXChild; + origInJSXTag = state.inJSXTag; + state.inJSXChild = false; + state.inJSXTag = true; expect('<'); expect('/'); - name = parseXJSElementName(); + name = parseJSXElementName(); // Because advance() (called by lex() called by expect()) expects there // to be a valid token after >, it needs to know whether to look for a - // standard JS token or an XJS text node - state.inXJSChild = origInXJSChild; - state.inXJSTag = origInXJSTag; + // standard JS token or an JSX text node + state.inJSXChild = origInJSXChild; + state.inJSXTag = origInJSXTag; expect('>'); - return markerApply(marker, delegate.createXJSClosingElement(name)); + return markerApply(marker, delegate.createJSXClosingElement(name)); } - function parseXJSOpeningElement() { - var name, attribute, attributes = [], selfClosing = false, origInXJSChild, origInXJSTag, marker = markerCreate(); + function parseJSXOpeningElement() { + var name, attributes = [], selfClosing = false, origInJSXChild, origInJSXTag, marker = markerCreate(); - origInXJSChild = state.inXJSChild; - origInXJSTag = state.inXJSTag; - state.inXJSChild = false; - state.inXJSTag = true; + origInJSXChild = state.inJSXChild; + origInJSXTag = state.inJSXTag; + state.inJSXChild = false; + state.inJSXTag = true; expect('<'); - name = parseXJSElementName(); + name = parseJSXElementName(); while (index < length && lookahead.value !== '/' && lookahead.value !== '>') { - attributes.push(parseXJSAttribute()); + attributes.push(parseJSXAttribute()); } - state.inXJSTag = origInXJSTag; + state.inJSXTag = origInJSXTag; if (lookahead.value === '/') { expect('/'); // Because advance() (called by lex() called by expect()) expects // there to be a valid token after >, it needs to know whether to - // look for a standard JS token or an XJS text node - state.inXJSChild = origInXJSChild; + // look for a standard JS token or an JSX text node + state.inJSXChild = origInJSXChild; expect('>'); selfClosing = true; } else { - state.inXJSChild = true; + state.inJSXChild = true; expect('>'); } - return markerApply(marker, delegate.createXJSOpeningElement(name, attributes, selfClosing)); + return markerApply(marker, delegate.createJSXOpeningElement(name, attributes, selfClosing)); } - function parseXJSElement() { - var openingElement, closingElement = null, children = [], origInXJSChild, origInXJSTag, marker = markerCreate(); + function parseJSXElement() { + var openingElement, closingElement = null, children = [], origInJSXChild, origInJSXTag, marker = markerCreate(); - origInXJSChild = state.inXJSChild; - origInXJSTag = state.inXJSTag; - openingElement = parseXJSOpeningElement(); + origInJSXChild = state.inJSXChild; + origInJSXTag = state.inJSXTag; + openingElement = parseJSXOpeningElement(); if (!openingElement.selfClosing) { while (index < length) { - state.inXJSChild = false; // Call lookahead2() with inXJSChild = false because one
two
; // // the default error message is a bit incomprehensible. Since it's - // rarely (never?) useful to write a less-than sign after an XJS + // rarely (never?) useful to write a less-than sign after an JSX // element, we disallow it here in the parser in order to provide a // better error message. (In the rare case that the less-than operator // was intended, the left tag can be wrapped in parentheses.) - if (!origInXJSChild && match('<')) { - throwError(lookahead, Messages.AdjacentXJSElements); + if (!origInJSXChild && match('<')) { + throwError(lookahead, Messages.AdjacentJSXElements); } - return markerApply(marker, delegate.createXJSElement(openingElement, closingElement, children)); + return markerApply(marker, delegate.createJSXElement(openingElement, closingElement, children)); } function parseTypeAlias() { @@ -9098,10 +9534,14 @@ parseYieldExpression: true, parseAwaitExpression: true } function parseInterface() { - var body, bodyMarker, extended = [], id, marker = markerCreate(), - typeParameters = null; + var marker = markerCreate(); + + if (strict) { + expectKeyword('interface'); + } else { + expectContextualKeyword('interface'); + } - expectContextualKeyword('interface'); return parseInterfaceish(marker, /* allowStatic */false); } @@ -9212,13 +9652,13 @@ parseYieldExpression: true, parseAwaitExpression: true } function collectToken() { - var start, loc, token, range, value, entry; + var loc, token, range, value, entry; - if (!state.inXJSChild) { + /* istanbul ignore else */ + if (!state.inJSXChild) { skipComment(); } - start = index; loc = { start: { line: lineNumber, @@ -9273,6 +9713,7 @@ parseYieldExpression: true, parseAwaitExpression: true }; if (!extra.tokenize) { + /* istanbul ignore next */ // Pop the previous token, which is likely '/' or '/=' if (extra.tokens.length > 0) { token = extra.tokens[extra.tokens.length - 1]; @@ -9323,11 +9764,6 @@ parseYieldExpression: true, parseAwaitExpression: true } function patch() { - if (extra.comments) { - extra.skipComment = skipComment; - skipComment = scanComment; - } - if (typeof extra.tokens !== 'undefined') { extra.advance = advance; extra.scanRegExp = scanRegExp; @@ -9338,10 +9774,6 @@ parseYieldExpression: true, parseAwaitExpression: true } function unpatch() { - if (typeof extra.skipComment === 'function') { - skipComment = extra.skipComment; - } - if (typeof extra.scanRegExp === 'function') { advance = extra.advance; scanRegExp = extra.scanRegExp; @@ -9354,12 +9786,14 @@ parseYieldExpression: true, parseAwaitExpression: true var entry, result = {}; for (entry in object) { + /* istanbul ignore else */ if (object.hasOwnProperty(entry)) { result[entry] = object[entry]; } } for (entry in properties) { + /* istanbul ignore else */ if (properties.hasOwnProperty(entry)) { result[entry] = properties[entry]; } @@ -9388,7 +9822,7 @@ parseYieldExpression: true, parseAwaitExpression: true state = { allowKeyword: true, allowIn: true, - labelSet: {}, + labelSet: new StringMap(), inFunctionBody: false, inIteration: false, inSwitch: false, @@ -9418,17 +9852,6 @@ parseYieldExpression: true, parseAwaitExpression: true extra.errors = []; } - if (length > 0) { - if (typeof source[0] === 'undefined') { - // Try first to convert to a string. This is good as fast path - // for old IE which understands string indexing for string - // literals only and not for string object. - if (code instanceof String) { - source = code.valueOf(); - } - } - } - patch(); try { @@ -9489,13 +9912,13 @@ parseYieldExpression: true, parseAwaitExpression: true state = { allowKeyword: false, allowIn: true, - labelSet: {}, + labelSet: new StringMap(), parenthesizedCount: 0, inFunctionBody: false, inIteration: false, inSwitch: false, - inXJSChild: false, - inXJSTag: false, + inJSXChild: false, + inJSXTag: false, inType: false, lastCommentStart: -1, yieldAllowed: false, @@ -9517,6 +9940,7 @@ parseYieldExpression: true, parseAwaitExpression: true }); } + extra.sourceType = options.sourceType; if (typeof options.tokens === 'boolean' && options.tokens) { extra.tokens = []; } @@ -9535,17 +9959,6 @@ parseYieldExpression: true, parseAwaitExpression: true } } - if (length > 0) { - if (typeof source[0] === 'undefined') { - // Try first to convert to a string. This is good as fast path - // for old IE which understands string indexing for string - // literals only and not for string object. - if (code instanceof String) { - source = code.valueOf(); - } - } - } - patch(); try { program = parseProgram(); @@ -9570,13 +9983,14 @@ parseYieldExpression: true, parseAwaitExpression: true } // Sync with *.json manifests. - exports.version = '8001.1001.0-dev-harmony-fb'; + exports.version = '13001.1001.0-dev-harmony-fb'; exports.tokenize = tokenize; exports.parse = parse; // Deep copy. + /* istanbul ignore next */ exports.Syntax = (function () { var name, types = {}; @@ -9601,25 +10015,53 @@ parseYieldExpression: true, parseAwaitExpression: true /* vim: set sw=4 ts=4 et tw=80 : */ },{}],10:[function(_dereq_,module,exports){ -/* - * Copyright 2009-2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE.txt or: - * http://opensource.org/licenses/BSD-3-Clause - */ -exports.SourceMapGenerator = _dereq_('./source-map/source-map-generator').SourceMapGenerator; -exports.SourceMapConsumer = _dereq_('./source-map/source-map-consumer').SourceMapConsumer; -exports.SourceNode = _dereq_('./source-map/source-node').SourceNode; +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"] -},{"./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 - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ -if (typeof define !== 'function') { - var define = _dereq_('amdefine')(module, _dereq_); -} + 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 +},{}],11:[function(_dereq_,module,exports){ +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ +exports.SourceMapGenerator = _dereq_('./source-map/source-map-generator').SourceMapGenerator; +exports.SourceMapConsumer = _dereq_('./source-map/source-map-consumer').SourceMapConsumer; +exports.SourceNode = _dereq_('./source-map/source-node').SourceNode; + +},{"./source-map/source-map-consumer":16,"./source-map/source-map-generator":17,"./source-map/source-node":18}],12:[function(_dereq_,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = _dereq_('amdefine')(module, _dereq_); +} define(function (_dereq_, exports, module) { var util = _dereq_('./util'); @@ -9709,7 +10151,7 @@ define(function (_dereq_, exports, module) { }); -},{"./util":18,"amdefine":19}],12:[function(_dereq_,module,exports){ +},{"./util":19,"amdefine":20}],13:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -9855,7 +10297,7 @@ define(function (_dereq_, exports, module) { }); -},{"./base64":13,"amdefine":19}],13:[function(_dereq_,module,exports){ +},{"./base64":14,"amdefine":20}],14:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -9899,7 +10341,7 @@ define(function (_dereq_, exports, module) { }); -},{"amdefine":19}],14:[function(_dereq_,module,exports){ +},{"amdefine":20}],15:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -9982,7 +10424,7 @@ define(function (_dereq_, exports, module) { }); -},{"amdefine":19}],15:[function(_dereq_,module,exports){ +},{"amdefine":20}],16:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -10461,7 +10903,7 @@ define(function (_dereq_, exports, module) { }); -},{"./array-set":11,"./base64-vlq":12,"./binary-search":14,"./util":18,"amdefine":19}],16:[function(_dereq_,module,exports){ +},{"./array-set":12,"./base64-vlq":13,"./binary-search":15,"./util":19,"amdefine":20}],17:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -10843,7 +11285,7 @@ define(function (_dereq_, exports, module) { }); -},{"./array-set":11,"./base64-vlq":12,"./util":18,"amdefine":19}],17:[function(_dereq_,module,exports){ +},{"./array-set":12,"./base64-vlq":13,"./util":19,"amdefine":20}],18:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -11216,7 +11658,7 @@ define(function (_dereq_, exports, module) { }); -},{"./source-map-generator":16,"./util":18,"amdefine":19}],18:[function(_dereq_,module,exports){ +},{"./source-map-generator":17,"./util":19,"amdefine":20}],19:[function(_dereq_,module,exports){ /* -*- Mode: js; js-indent-level: 2; -*- */ /* * Copyright 2011 Mozilla Foundation and contributors @@ -11423,7 +11865,7 @@ define(function (_dereq_, exports, module) { }); -},{"amdefine":19}],19:[function(_dereq_,module,exports){ +},{"amdefine":20}],20:[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. @@ -11726,7 +12168,7 @@ function amdefine(module, requireFn) { module.exports = amdefine; }).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){ +},{"_process":8,"path":7}],21:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -11814,7 +12256,7 @@ exports.extract = extract; exports.parse = parse; exports.parseAsObject = parseAsObject; -},{}],21:[function(_dereq_,module,exports){ +},{}],22:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -11858,7 +12300,12 @@ function _nodeIsClosureScopeBoundary(node, parentNode) { || parentNode.type === Syntax.FunctionExpression || parentNode.type === Syntax.ArrowFunctionExpression; - return node.type === Syntax.BlockStatement && parentIsFunction; + var parentIsCurlylessArrowFunc = + parentNode.type === Syntax.ArrowFunctionExpression + && node === parentNode.body; + + return parentIsFunction + && (node.type === Syntax.BlockStatement || parentIsCurlylessArrowFunc); } function _nodeIsBlockScopeBoundary(node, parentNode) { @@ -11876,29 +12323,38 @@ function _nodeIsBlockScopeBoundary(node, parentNode) { * @param {object} state */ function traverse(node, path, state) { + /*jshint -W004*/ // Create a scope stack entry if this is the first node we've encountered in // its local scope + var startIndex = null; var parentNode = path[0]; if (!Array.isArray(node) && state.localScope.parentNode !== parentNode) { if (_nodeIsClosureScopeBoundary(node, parentNode)) { - var scopeIsStrict = - state.scopeIsStrict - || node.body.length > 0 - && node.body[0].type === Syntax.ExpressionStatement - && node.body[0].expression.type === Syntax.Literal - && node.body[0].expression.value === 'use strict'; + var scopeIsStrict = state.scopeIsStrict; + if (!scopeIsStrict + && (node.type === Syntax.BlockStatement + || node.type === Syntax.Program)) { + scopeIsStrict = + node.body.length > 0 + && node.body[0].type === Syntax.ExpressionStatement + && node.body[0].expression.type === Syntax.Literal + && node.body[0].expression.value === 'use strict'; + } if (node.type === Syntax.Program) { + startIndex = state.g.buffer.length; state = utils.updateState(state, { scopeIsStrict: scopeIsStrict }); } else { + startIndex = state.g.buffer.length + 1; state = utils.updateState(state, { localScope: { parentNode: parentNode, parentScope: state.localScope, identifiers: {}, - tempVarIndex: 0 + tempVarIndex: 0, + tempVars: [] }, scopeIsStrict: scopeIsStrict }); @@ -11910,16 +12366,26 @@ function traverse(node, path, state) { // function if (parentNode.params.length > 0) { var param; + var metadata = initScopeMetadata(parentNode, path.slice(1), path[0]); for (var i = 0; i < parentNode.params.length; i++) { param = parentNode.params[i]; if (param.type === Syntax.Identifier) { - declareIdentInScope( - param.name, initScopeMetadata(parentNode), state - ); + declareIdentInScope(param.name, metadata, state); } } } + // Include rest arg identifiers in the scope boundaries of their + // functions + if (parentNode.rest) { + var metadata = initScopeMetadata( + parentNode, + path.slice(1), + path[0] + ); + declareIdentInScope(parentNode.rest.name, metadata, state); + } + // Named FunctionExpressions scope their name within the body block of // themselves only if (parentNode.type === Syntax.FunctionExpression && parentNode.id) { @@ -11935,18 +12401,24 @@ function traverse(node, path, state) { } if (_nodeIsBlockScopeBoundary(node, parentNode)) { + startIndex = state.g.buffer.length; state = utils.updateState(state, { localScope: { parentNode: parentNode, parentScope: state.localScope, - identifiers: {} + identifiers: {}, + tempVarIndex: 0, + tempVars: [] } }); if (parentNode.type === Syntax.CatchClause) { - declareIdentInScope( - parentNode.param.name, initScopeMetadata(parentNode), state + var metadata = initScopeMetadata( + parentNode, + path.slice(1), + parentNode ); + declareIdentInScope(parentNode.param.name, metadata, state); } collectBlockIdentsAndTraverse(node, path, state); } @@ -11960,6 +12432,11 @@ function traverse(node, path, state) { } utils.analyzeAndTraverse(walker, traverser, node, path, state); + + // Inject temp variables into the scope. + if (startIndex !== null) { + utils.injectTempVarDeclarations(state, startIndex); + } } function collectClosureIdentsAndTraverse(node, path, state) { @@ -11985,6 +12462,7 @@ function collectBlockIdentsAndTraverse(node, path, state) { function visitLocalClosureIdentifiers(node, path, state) { var metaData; switch (node.type) { + case Syntax.ArrowFunctionExpression: case Syntax.FunctionExpression: // Function expressions don't get their names (if there is one) added to // the closure scope they're defined in @@ -12025,6 +12503,22 @@ function walker(node, path, state) { var _astCache = {}; +function getAstForSource(source, options) { + if (_astCache[source] && !options.disableAstCache) { + return _astCache[source]; + } + var ast = esprima.parse(source, { + comment: true, + loc: true, + range: true, + sourceType: options.sourceType + }); + if (!options.disableAstCache) { + _astCache[source] = ast; + } + return ast; +} + /** * Applies all available transformations to the source * @param {array} visitors @@ -12036,13 +12530,7 @@ function transform(visitors, source, options) { options = options || {}; var ast; try { - var cachedAst = _astCache[source]; - ast = cachedAst || - (_astCache[source] = esprima.parse(source, { - comment: true, - loc: true, - range: true - })); + ast = getAstForSource(source, options); } catch (e) { e.message = 'Parse Error: ' + e.message; throw e; @@ -12069,7 +12557,7 @@ function transform(visitors, source, options) { exports.transform = transform; exports.Syntax = Syntax; -},{"./utils":22,"esprima-fb":9,"source-map":10}],22:[function(_dereq_,module,exports){ +},{"./utils":23,"esprima-fb":9,"source-map":11}],23:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -12114,7 +12602,8 @@ function createState(source, rootNode, transformOptions) { parentNode: rootNode, parentScope: null, identifiers: {}, - tempVarIndex: 0 + tempVarIndex: 0, + tempVars: [] }, /** * The name (and, if applicable, expression) of the super class @@ -12331,29 +12820,87 @@ function getNodeSourceText(node, state) { return state.g.source.substring(node.range[0], node.range[1]); } -function replaceNonWhite(value) { +function _replaceNonWhite(value) { return value.replace(nonWhiteRegexp, ' '); } /** * Removes all non-whitespace characters */ -function stripNonWhite(value) { +function _stripNonWhite(value) { return value.replace(nonWhiteRegexp, ''); } +/** + * Finds the position of the next instance of the specified syntactic char in + * the pending source. + * + * NOTE: This will skip instances of the specified char if they sit inside a + * comment body. + * + * NOTE: This function also assumes that the buffer's current position is not + * already within a comment or a string. This is rarely the case since all + * of the buffer-advancement utility methods tend to be used on syntactic + * nodes' range values -- but it's a small gotcha that's worth mentioning. + */ +function getNextSyntacticCharOffset(char, state) { + var pendingSource = state.g.source.substring(state.g.position); + var pendingSourceLines = pendingSource.split('\n'); + + var charOffset = 0; + var line; + var withinBlockComment = false; + var withinString = false; + lineLoop: while ((line = pendingSourceLines.shift()) !== undefined) { + var lineEndPos = charOffset + line.length; + charLoop: for (; charOffset < lineEndPos; charOffset++) { + var currChar = pendingSource.charAt(charOffset); + if (currChar === '"' || currChar === '\'') { + withinString = !withinString; + continue charLoop; + } else if (withinString) { + continue charLoop; + } else if (charOffset + 1 < lineEndPos) { + var nextTwoChars = currChar + line[charOffset + 1]; + if (nextTwoChars === '//') { + charOffset = lineEndPos + 1; + continue lineLoop; + } else if (nextTwoChars === '/*') { + withinBlockComment = true; + charOffset += 1; + continue charLoop; + } else if (nextTwoChars === '*/') { + withinBlockComment = false; + charOffset += 1; + continue charLoop; + } + } + + if (!withinBlockComment && currChar === char) { + return charOffset + state.g.position; + } + } + + // Account for '\n' + charOffset++; + withinString = false; + } + + throw new Error('`' + char + '` not found!'); +} + /** * Catches up as `catchup` but replaces non-whitespace chars with spaces. */ function catchupWhiteOut(end, state) { - catchup(end, state, replaceNonWhite); + catchup(end, state, _replaceNonWhite); } /** * Catches up as `catchup` but removes all non-whitespace characters. */ function catchupWhiteSpace(end, state) { - catchup(end, state, stripNonWhite); + catchup(end, state, _stripNonWhite); } /** @@ -12436,6 +12983,7 @@ function append(str, state) { * @return {string} */ function updateIndent(str, state) { + /*jshint -W004*/ var indentBy = state.indentBy; if (indentBy < 0) { for (var i = 0; i < -indentBy; i++) { @@ -12527,6 +13075,17 @@ function declareIdentInLocalScope(identName, metaData, state) { } function getLexicalBindingMetadata(identName, state) { + var currScope = state.localScope; + while (currScope) { + if (currScope.identifiers[identName] !== undefined) { + return currScope.identifiers[identName]; + } + + currScope = currScope.parentScope; + } +} + +function getLocalBindingMetadata(identName, state) { return state.localScope.identifiers[identName]; } @@ -12642,6 +13201,7 @@ function containsChildMatching(node, matcher) { } var scopeTypes = {}; +scopeTypes[Syntax.ArrowFunctionExpression] = true; scopeTypes[Syntax.FunctionExpression] = true; scopeTypes[Syntax.FunctionDeclaration] = true; scopeTypes[Syntax.Program] = true; @@ -12662,15 +13222,28 @@ function getTempVar(tempVarIndex) { return '$__' + tempVarIndex; } -function getTempVarWithValue(tempVarIndex, tempVarValue) { - return getTempVar(tempVarIndex) + '=' + tempVarValue; +function injectTempVar(state) { + var tempVar = '$__' + (state.localScope.tempVarIndex++); + state.localScope.tempVars.push(tempVar); + return tempVar; +} + +function injectTempVarDeclarations(state, index) { + if (state.localScope.tempVars.length) { + state.g.buffer = + state.g.buffer.slice(0, index) + + 'var ' + state.localScope.tempVars.join(', ') + ';' + + state.g.buffer.slice(index); + state.localScope.tempVars = []; + } } +exports.analyzeAndTraverse = analyzeAndTraverse; exports.append = append; exports.catchup = catchup; +exports.catchupNewlines = catchupNewlines; exports.catchupWhiteOut = catchupWhiteOut; exports.catchupWhiteSpace = catchupWhiteSpace; -exports.catchupNewlines = catchupNewlines; exports.containsChildMatching = containsChildMatching; exports.containsChildOfType = containsChildOfType; exports.createState = createState; @@ -12678,21 +13251,23 @@ exports.declareIdentInLocalScope = declareIdentInLocalScope; exports.getBoundaryNode = getBoundaryNode; exports.getDocblock = getDocblock; exports.getLexicalBindingMetadata = getLexicalBindingMetadata; -exports.initScopeMetadata = initScopeMetadata; -exports.identWithinLexicalScope = identWithinLexicalScope; +exports.getLocalBindingMetadata = getLocalBindingMetadata; +exports.getNextSyntacticCharOffset = getNextSyntacticCharOffset; +exports.getNodeSourceText = getNodeSourceText; +exports.getOrderedChildren = getOrderedChildren; +exports.getTempVar = getTempVar; exports.identInLocalScope = identInLocalScope; +exports.identWithinLexicalScope = identWithinLexicalScope; exports.indentBefore = indentBefore; +exports.initScopeMetadata = initScopeMetadata; +exports.injectTempVar = injectTempVar; +exports.injectTempVarDeclarations = injectTempVarDeclarations; exports.move = move; exports.scopeTypes = scopeTypes; exports.updateIndent = updateIndent; exports.updateState = updateState; -exports.analyzeAndTraverse = analyzeAndTraverse; -exports.getOrderedChildren = getOrderedChildren; -exports.getNodeSourceText = getNodeSourceText; -exports.getTempVar = getTempVar; -exports.getTempVarWithValue = getTempVarWithValue; -},{"./docblock":20,"esprima-fb":9}],23:[function(_dereq_,module,exports){ +},{"./docblock":21,"esprima-fb":9}],24:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -12852,7 +13427,116 @@ exports.visitorList = [ ]; -},{"../src/utils":22,"./es6-destructuring-visitors":25,"./es6-rest-param-visitors":28,"esprima-fb":9}],24:[function(_dereq_,module,exports){ +},{"../src/utils":23,"./es6-destructuring-visitors":27,"./es6-rest-param-visitors":30,"esprima-fb":9}],25:[function(_dereq_,module,exports){ +/** + * Copyright 2004-present Facebook. All Rights Reserved. + */ +/*global exports:true*/ + +/** + * Implements ES6 call spread. + * + * instance.method(a, b, c, ...d) + * + * instance.method.apply(instance, [a, b, c].concat(d)) + * + */ + +var Syntax = _dereq_('esprima-fb').Syntax; +var utils = _dereq_('../src/utils'); + +function process(traverse, node, path, state) { + utils.move(node.range[0], state); + traverse(node, path, state); + utils.catchup(node.range[1], state); +} + +function visitCallSpread(traverse, node, path, state) { + utils.catchup(node.range[0], state); + + if (node.type === Syntax.NewExpression) { + // Input = new Set(1, 2, ...list) + // Output = new (Function.prototype.bind.apply(Set, [null, 1, 2].concat(list))) + utils.append('new (Function.prototype.bind.apply(', state); + process(traverse, node.callee, path, state); + } else if (node.callee.type === Syntax.MemberExpression) { + // Input = get().fn(1, 2, ...more) + // Output = (_ = get()).fn.apply(_, [1, 2].apply(more)) + var tempVar = utils.injectTempVar(state); + utils.append('(' + tempVar + ' = ', state); + process(traverse, node.callee.object, path, state); + utils.append(')', state); + if (node.callee.property.type === Syntax.Identifier) { + utils.append('.', state); + process(traverse, node.callee.property, path, state); + } else { + utils.append('[', state); + process(traverse, node.callee.property, path, state); + utils.append(']', state); + } + utils.append('.apply(' + tempVar, state); + } else { + // Input = max(1, 2, ...list) + // Output = max.apply(null, [1, 2].concat(list)) + var needsToBeWrappedInParenthesis = + node.callee.type === Syntax.FunctionDeclaration || + node.callee.type === Syntax.FunctionExpression; + if (needsToBeWrappedInParenthesis) { + utils.append('(', state); + } + process(traverse, node.callee, path, state); + if (needsToBeWrappedInParenthesis) { + utils.append(')', state); + } + utils.append('.apply(null', state); + } + utils.append(', ', state); + + var args = node.arguments.slice(); + var spread = args.pop(); + if (args.length || node.type === Syntax.NewExpression) { + utils.append('[', state); + if (node.type === Syntax.NewExpression) { + utils.append('null' + (args.length ? ', ' : ''), state); + } + while (args.length) { + var arg = args.shift(); + utils.move(arg.range[0], state); + traverse(arg, path, state); + if (args.length) { + utils.catchup(args[0].range[0], state); + } else { + utils.catchup(arg.range[1], state); + } + } + utils.append('].concat(', state); + process(traverse, spread.argument, path, state); + utils.append(')', state); + } else { + process(traverse, spread.argument, path, state); + } + utils.append(node.type === Syntax.NewExpression ? '))' : ')', state); + + utils.move(node.range[1], state); + return false; +} + +visitCallSpread.test = function(node, path, state) { + return ( + ( + node.type === Syntax.CallExpression || + node.type === Syntax.NewExpression + ) && + node.arguments.length > 0 && + node.arguments[node.arguments.length - 1].type === Syntax.SpreadElement + ); +}; + +exports.visitorList = [ + visitCallSpread +]; + +},{"../src/utils":23,"esprima-fb":9}],26:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -13036,6 +13720,7 @@ function visitClassFunctionExpression(traverse, node, path, state) { if (methodNode.key.name === 'constructor') { utils.append('function ' + state.className, state); } else { + var methodAccessorComputed = false; var methodAccessor; var prototypeOrStatic = methodNode["static"] ? '' : '.prototype'; var objectAccessor = state.className + prototypeOrStatic; @@ -13049,16 +13734,13 @@ function visitClassFunctionExpression(traverse, node, path, state) { if (isGetter || isSetter) { methodAccessor = JSON.stringify(methodAccessor); } else if (reservedWordsHelper.isReservedWord(methodAccessor)) { - methodAccessor = '[' + JSON.stringify(methodAccessor) + ']'; - } else { - methodAccessor = '.' + methodAccessor; + methodAccessorComputed = true; + methodAccessor = JSON.stringify(methodAccessor); } } else if (methodNode.key.type === Syntax.Literal) { // 'foo bar'() {} | get 'foo bar'() {} | set 'foo bar'() {} methodAccessor = JSON.stringify(methodNode.key.value); - if (!(isGetter || isSetter)) { - methodAccessor = '[' + methodAccessor + ']'; - } + methodAccessorComputed = true; } if (isSetter || isGetter) { @@ -13066,16 +13748,35 @@ function visitClassFunctionExpression(traverse, node, path, state) { 'Object.defineProperty(' + objectAccessor + ',' + methodAccessor + ',' + - '{enumerable:true,configurable:true,' + + '{configurable:true,' + methodNode.kind + ':function', state ); } else { - utils.append( - objectAccessor + - methodAccessor + '=function' + (node.generator ? '*' : ''), - state - ); + if (state.g.opts.es3) { + if (methodAccessorComputed) { + methodAccessor = '[' + methodAccessor + ']'; + } else { + methodAccessor = '.' + methodAccessor; + } + utils.append( + objectAccessor + + methodAccessor + '=function' + (node.generator ? '*' : ''), + state + ); + } else { + if (!methodAccessorComputed) { + methodAccessor = JSON.stringify(methodAccessor); + } + utils.append( + 'Object.defineProperty(' + + objectAccessor + ',' + + methodAccessor + ',' + + '{writable:true,configurable:true,' + + 'value:function' + (node.generator ? '*' : ''), + state + ); + } } } utils.move(methodNode.key.range[1], state); @@ -13091,9 +13792,13 @@ function visitClassFunctionExpression(traverse, node, path, state) { path.shift(); } } - utils.append(')', state); - utils.catchupWhiteSpace(node.body.range[0], state); - utils.append('{', state); + + var closingParenPosition = utils.getNextSyntacticCharOffset(')', state); + utils.catchupWhiteSpace(closingParenPosition, state); + + var openingBracketPosition = utils.getNextSyntacticCharOffset('{', state); + utils.catchup(openingBracketPosition + 1, state); + if (!state.scopeIsStrict) { utils.append('"use strict";', state); state = utils.updateState(state, { @@ -13108,7 +13813,7 @@ function visitClassFunctionExpression(traverse, node, path, state) { utils.catchup(node.body.range[1], state); if (methodNode.key.name !== 'constructor') { - if (isGetter || isSetter) { + if (isGetter || isSetter || !state.g.opts.es3) { utils.append('})', state); } utils.append(';', state); @@ -13421,7 +14126,7 @@ exports.visitorList = [ visitSuperMemberExpression ]; -},{"../src/utils":22,"./reserved-words-helper":32,"base62":8,"esprima-fb":9}],25:[function(_dereq_,module,exports){ +},{"../src/utils":23,"./reserved-words-helper":34,"base62":10,"esprima-fb":9}],27:[function(_dereq_,module,exports){ /** * Copyright 2014 Facebook, Inc. * @@ -13543,7 +14248,7 @@ function getDestructuredComponents(node, state) { } else { // Complex sub-structure. components.push( - utils.getTempVarWithValue(++state.localScope.tempVarIndex, accessor) + + utils.getTempVar(++state.localScope.tempVarIndex) + '=' + accessor + ',' + getDestructuredComponents(value, state) ); } @@ -13703,7 +14408,7 @@ exports.visitorList = [ exports.renderDestructuredComponents = renderDestructuredComponents; -},{"../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){ +},{"../src/utils":23,"./es6-rest-param-visitors":30,"./es7-rest-property-helpers":32,"./reserved-words-helper":34,"esprima-fb":9}],28:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -13774,7 +14479,7 @@ exports.visitorList = [ visitObjectConciseMethod ]; -},{"../src/utils":22,"./reserved-words-helper":32,"esprima-fb":9}],27:[function(_dereq_,module,exports){ +},{"../src/utils":23,"./reserved-words-helper":34,"esprima-fb":9}],29:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -13829,7 +14534,7 @@ exports.visitorList = [ ]; -},{"../src/utils":22,"esprima-fb":9}],28:[function(_dereq_,module,exports){ +},{"../src/utils":23,"esprima-fb":9}],30:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -13912,8 +14617,8 @@ function renderRestParamSetup(functionNode, state) { 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) + '=' + functionNode.params.length + ',' + + utils.getTempVar(len) + '=arguments.length;' + utils.getTempVar(idx) + '<' + utils.getTempVar(len) + ';' + utils.getTempVar(idx) + '++) ' + functionNode.rest.name + '.push(arguments[' + utils.getTempVar(idx) + ']);'; @@ -13937,7 +14642,7 @@ exports.visitorList = [ visitFunctionBodyWithRestParam ]; -},{"../src/utils":22,"esprima-fb":9}],29:[function(_dereq_,module,exports){ +},{"../src/utils":23,"esprima-fb":9}],31:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -14095,7 +14800,7 @@ exports.visitorList = [ visitTaggedTemplateExpression ]; -},{"../src/utils":22,"esprima-fb":9}],30:[function(_dereq_,module,exports){ +},{"../src/utils":23,"esprima-fb":9}],32:[function(_dereq_,module,exports){ /** * Copyright 2013 Facebook, Inc. * @@ -14119,7 +14824,6 @@ exports.visitorList = [ */ 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. @@ -14178,7 +14882,7 @@ function renderRestExpression(accessorExpression, excludedProperties) { exports.renderRestExpression = renderRestExpression; -},{"../src/utils":22,"esprima-fb":9}],31:[function(_dereq_,module,exports){ +},{"esprima-fb":9}],33:[function(_dereq_,module,exports){ /** * Copyright 2004-present Facebook. All Rights Reserved. */ @@ -14288,7 +14992,7 @@ exports.visitorList = [ visitObjectLiteralSpread ]; -},{"../src/utils":22,"esprima-fb":9}],32:[function(_dereq_,module,exports){ +},{"../src/utils":23,"esprima-fb":9}],34:[function(_dereq_,module,exports){ /** * Copyright 2014 Facebook, Inc. * @@ -14335,11 +15039,106 @@ RESERVED_WORDS.forEach(function(k) { reservedWordsMap[k] = true; }); +/** + * This list should not grow as new reserved words are introdued. This list is + * of words that need to be quoted because ES3-ish browsers do not allow their + * use as identifier names. + */ +var ES3_FUTURE_RESERVED_WORDS = [ + 'enum', 'implements', 'package', 'protected', 'static', 'interface', + 'private', 'public' +]; + +var ES3_RESERVED_WORDS = [].concat( + KEYWORDS, + ES3_FUTURE_RESERVED_WORDS, + LITERALS +); + +var es3ReservedWordsMap = Object.create(null); +ES3_RESERVED_WORDS.forEach(function(k) { + es3ReservedWordsMap[k] = true; +}); + exports.isReservedWord = function(word) { return !!reservedWordsMap[word]; }; -},{}],33:[function(_dereq_,module,exports){ +exports.isES3ReservedWord = function(word) { + return !!es3ReservedWordsMap[word]; +}; + +},{}],35:[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. + * + */ +/*global exports:true*/ + +var Syntax = _dereq_('esprima-fb').Syntax; +var utils = _dereq_('../src/utils'); +var reserverdWordsHelper = _dereq_('./reserved-words-helper'); + +/** + * Code adapted from https://github.com/spicyj/es3ify + * The MIT License (MIT) + * Copyright (c) 2014 Ben Alpert + */ + +function visitProperty(traverse, node, path, state) { + utils.catchup(node.key.range[0], state); + utils.append('"', state); + utils.catchup(node.key.range[1], state); + utils.append('"', state); + utils.catchup(node.value.range[0], state); + traverse(node.value, path, state); + return false; +} + +visitProperty.test = function(node) { + return node.type === Syntax.Property && + node.key.type === Syntax.Identifier && + !node.method && + !node.shorthand && + !node.computed && + reserverdWordsHelper.isES3ReservedWord(node.key.name); +}; + +function visitMemberExpression(traverse, node, path, state) { + traverse(node.object, path, state); + utils.catchup(node.property.range[0] - 1, state); + utils.append('[', state); + utils.catchupWhiteSpace(node.property.range[0], state); + utils.append('"', state); + utils.catchup(node.property.range[1], state); + utils.append('"]', state); + return false; +} + +visitMemberExpression.test = function(node) { + return node.type === Syntax.MemberExpression && + node.property.type === Syntax.Identifier && + reserverdWordsHelper.isES3ReservedWord(node.property.name); +}; + +exports.visitorList = [ + visitProperty, + visitMemberExpression +]; + +},{"../src/utils":23,"./reserved-words-helper":34,"esprima-fb":9}],36:[function(_dereq_,module,exports){ var esprima = _dereq_('esprima-fb'); var utils = _dereq_('../src/utils'); @@ -14368,6 +15167,19 @@ visitTypeAlias.test = function(node, path, state) { return node.type === Syntax.TypeAlias; }; +function visitTypeCast(traverse, node, path, state) { + path.unshift(node); + traverse(node.expression, path, state); + path.shift(); + + utils.catchup(node.typeAnnotation.range[0], state); + utils.catchupWhiteOut(node.typeAnnotation.range[1], state); + return false; +} +visitTypeCast.test = function(node, path, state) { + return node.type === Syntax.TypeCastExpression; +}; + function visitInterfaceDeclaration(traverse, node, path, state) { utils.catchupWhiteOut(node.range[1], state); return false; @@ -14382,13 +15194,14 @@ function visitDeclare(traverse, node, path, state) { } visitDeclare.test = function(node, path, state) { switch (node.type) { - case Syntax.DeclareVariable: - case Syntax.DeclareFunction: - case Syntax.DeclareClass: - case Syntax.DeclareModule: return true + 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); @@ -14475,22 +15288,33 @@ visitMethod.test = function(node, path, state) { || (node.type === "MethodDefinition"); }; +function visitImportType(traverse, node, path, state) { + utils.catchupWhiteOut(node.range[1], state); + return false; +} +visitImportType.test = function(node, path, state) { + return node.type === 'ImportDeclaration' + && node.isType; +}; + exports.visitorList = [ visitClassProperty, visitDeclare, + visitImportType, visitInterfaceDeclaration, visitFunctionParametricAnnotation, visitFunctionReturnAnnotation, visitMethod, visitOptionalFunctionParameterAnnotation, visitTypeAlias, + visitTypeCast, visitTypeAnnotatedIdentifier, visitTypeAnnotatedObjectOrArrayPattern ]; -},{"../src/utils":22,"esprima-fb":9}],34:[function(_dereq_,module,exports){ +},{"../src/utils":23,"esprima-fb":9}],37:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -14498,18 +15322,130 @@ exports.visitorList = [ * of patent rights can be found in the PATENTS file in the same directory. */ /*global exports:true*/ -"use strict"; +'use strict'; +var Syntax = _dereq_('jstransform').Syntax; +var utils = _dereq_('jstransform/src/utils'); + +function renderJSXLiteral(object, isLast, state, start, end) { + var lines = object.value.split(/\r\n|\n|\r/); + + if (start) { + utils.append(start, state); + } + + var lastNonEmptyLine = 0; + + lines.forEach(function(line, index) { + if (line.match(/[^ \t]/)) { + lastNonEmptyLine = index; + } + }); + + lines.forEach(function(line, index) { + var isFirstLine = index === 0; + var isLastLine = index === lines.length - 1; + var isLastNonEmptyLine = index === lastNonEmptyLine; + + // replace rendered whitespace tabs with spaces + var trimmedLine = line.replace(/\t/g, ' '); + + // trim whitespace touching a newline + if (!isFirstLine) { + trimmedLine = trimmedLine.replace(/^[ ]+/, ''); + } + if (!isLastLine) { + trimmedLine = trimmedLine.replace(/[ ]+$/, ''); + } + + if (!isFirstLine) { + utils.append(line.match(/^[ \t]*/)[0], state); + } + + if (trimmedLine || isLastNonEmptyLine) { + utils.append( + JSON.stringify(trimmedLine) + + (!isLastNonEmptyLine ? ' + \' \' +' : ''), + state); + + if (isLastNonEmptyLine) { + if (end) { + utils.append(end, state); + } + if (!isLast) { + utils.append(', ', state); + } + } + + // only restore tail whitespace if line had literals + if (trimmedLine && !isLastLine) { + utils.append(line.match(/[ \t]*$/)[0], state); + } + } + + if (!isLastLine) { + utils.append('\n', state); + } + }); + + utils.move(object.range[1], state); +} + +function renderJSXExpressionContainer(traverse, object, isLast, path, state) { + // Plus 1 to skip `{`. + utils.move(object.range[0] + 1, state); + utils.catchup(object.expression.range[0], state); + traverse(object.expression, path, state); + + if (!isLast && object.expression.type !== Syntax.JSXEmptyExpression) { + // If we need to append a comma, make sure to do so after the expression. + utils.catchup(object.expression.range[1], state, trimLeft); + utils.append(', ', state); + } + + // Minus 1 to skip `}`. + utils.catchup(object.range[1] - 1, state, trimLeft); + utils.move(object.range[1], state); + return false; +} + +function quoteAttrName(attr) { + // Quote invalid JS identifiers. + if (!/^[a-z_$][a-z\d_$]*$/i.test(attr)) { + return '"' + attr + '"'; + } + return attr; +} + +function trimLeft(value) { + return value.replace(/^[ ]+/, ''); +} + +exports.renderJSXExpressionContainer = renderJSXExpressionContainer; +exports.renderJSXLiteral = renderJSXLiteral; +exports.quoteAttrName = quoteAttrName; +exports.trimLeft = trimLeft; + +},{"jstransform":22,"jstransform/src/utils":23}],38:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, 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_('jstransform').Syntax; var utils = _dereq_('jstransform/src/utils'); -var FALLBACK_TAGS = _dereq_('./xjs').knownTags; -var renderXJSExpressionContainer = - _dereq_('./xjs').renderXJSExpressionContainer; -var renderXJSLiteral = _dereq_('./xjs').renderXJSLiteral; -var quoteAttrName = _dereq_('./xjs').quoteAttrName; +var renderJSXExpressionContainer = + _dereq_('./jsx').renderJSXExpressionContainer; +var renderJSXLiteral = _dereq_('./jsx').renderJSXLiteral; +var quoteAttrName = _dereq_('./jsx').quoteAttrName; -var trimLeft = _dereq_('./xjs').trimLeft; +var trimLeft = _dereq_('./jsx').trimLeft; /** * Customized desugar processor for React JSX. Currently: @@ -14542,30 +15478,20 @@ function visitReactTag(traverse, object, path, state) { utils.catchup(openingElement.range[0], state, trimLeft); - if (nameObject.type === Syntax.XJSNamespacedName && nameObject.namespace) { + if (nameObject.type === Syntax.JSXNamespacedName && nameObject.namespace) { throw new Error('Namespace tags are not supported. ReactJSX is not XML.'); } // 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( - 'Lower case component names (' + nameObject.name + ') are no longer ' + - 'supported in JSX: See http://fb.me/react-jsx-lower-case' - ); - } - + if (nameObject.type === Syntax.JSXIdentifier && isTagName(nameObject.name)) { 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. + // JSXMemberExpressions which look like Foo.Bar.Baz. This also handles + // JSXIdentifiers that aren't fallback tags. utils.move(nameObject.range[0], state); utils.catchup(nameObject.range[1], state); } @@ -14575,7 +15501,7 @@ function visitReactTag(traverse, object, path, state) { var hasAttributes = attributesObject.length; var hasAtLeastOneSpreadProperty = attributesObject.some(function(attr) { - return attr.type === Syntax.XJSSpreadAttribute; + return attr.type === Syntax.JSXSpreadAttribute; }); // if we don't have any attributes, pass in null @@ -14594,7 +15520,7 @@ function visitReactTag(traverse, object, path, state) { attributesObject.forEach(function(attr, index) { var isLast = index === attributesObject.length - 1; - if (attr.type === Syntax.XJSSpreadAttribute) { + if (attr.type === Syntax.JSXSpreadAttribute) { // Close the previous object or initial object if (!previousWasSpread) { utils.append('}, ', state); @@ -14627,7 +15553,7 @@ function visitReactTag(traverse, object, path, state) { // If the next attribute is a spread, we're effective last in this object if (!isLast) { - isLast = attributesObject[index + 1].type === Syntax.XJSSpreadAttribute; + isLast = attributesObject[index + 1].type === Syntax.JSXSpreadAttribute; } if (attr.name.namespace) { @@ -14656,9 +15582,9 @@ function visitReactTag(traverse, object, path, state) { // Use catchupNewlines to skip over the '=' in the attribute utils.catchupNewlines(attr.value.range[0], state); if (attr.value.type === Syntax.Literal) { - renderXJSLiteral(attr.value, isLast, state); + renderJSXLiteral(attr.value, isLast, state); } else { - renderXJSExpressionContainer(traverse, attr.value, isLast, path, state); + renderJSXExpressionContainer(traverse, attr.value, isLast, path, state); } } @@ -14691,8 +15617,8 @@ function visitReactTag(traverse, object, path, state) { var lastRenderableIndex; childrenToRender.forEach(function(child, index) { - if (child.type !== Syntax.XJSExpressionContainer || - child.expression.type !== Syntax.XJSEmptyExpression) { + if (child.type !== Syntax.JSXExpressionContainer || + child.expression.type !== Syntax.JSXEmptyExpression) { lastRenderableIndex = index; } }); @@ -14707,9 +15633,9 @@ function visitReactTag(traverse, object, path, state) { var isLast = index >= lastRenderableIndex; if (child.type === Syntax.Literal) { - renderXJSLiteral(child, isLast, state); - } else if (child.type === Syntax.XJSExpressionContainer) { - renderXJSExpressionContainer(traverse, child, isLast, path, state); + renderJSXLiteral(child, isLast, state); + } else if (child.type === Syntax.JSXExpressionContainer) { + renderJSXExpressionContainer(traverse, child, isLast, path, state); } else { traverse(child, path, state); if (!isLast) { @@ -14736,16 +15662,16 @@ function visitReactTag(traverse, object, path, state) { } visitReactTag.test = function(object, path, state) { - return object.type === Syntax.XJSElement; + return object.type === Syntax.JSXElement; }; exports.visitorList = [ visitReactTag ]; -},{"./xjs":36,"jstransform":21,"jstransform/src/utils":22}],35:[function(_dereq_,module,exports){ +},{"./jsx":37,"jstransform":22,"jstransform/src/utils":23}],39:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -14753,7 +15679,7 @@ exports.visitorList = [ * of patent rights can be found in the PATENTS file in the same directory. */ /*global exports:true*/ -"use strict"; +'use strict'; var Syntax = _dereq_('jstransform').Syntax; var utils = _dereq_('jstransform/src/utils'); @@ -14766,10 +15692,10 @@ function addDisplayName(displayName, object, state) { object.callee.object.name === 'React' && object.callee.property.type === Syntax.Identifier && object.callee.property.name === 'createClass' && - object['arguments'].length === 1 && - object['arguments'][0].type === Syntax.ObjectExpression) { + object.arguments.length === 1 && + object.arguments[0].type === Syntax.ObjectExpression) { // Verify that the displayName property isn't already set - var properties = object['arguments'][0].properties; + var properties = object.arguments[0].properties; var safe = properties.every(function(property) { var value = property.key.type === Syntax.Identifier ? property.key.name : @@ -14778,7 +15704,7 @@ function addDisplayName(displayName, object, state) { }); if (safe) { - utils.catchup(object['arguments'][0].range[0] + 1, state); + utils.catchup(object.arguments[0].range[0] + 1, state); utils.append('displayName: "' + displayName + '",', state); } } @@ -14838,267 +15764,29 @@ exports.visitorList = [ visitReactDisplayName ]; -},{"jstransform":21,"jstransform/src/utils":22}],36:[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. - */ +},{"jstransform":22,"jstransform/src/utils":23}],40:[function(_dereq_,module,exports){ /*global exports:true*/ -"use strict"; -var Syntax = _dereq_('jstransform').Syntax; -var utils = _dereq_('jstransform/src/utils'); - -var knownTags = { - a: true, - abbr: true, - address: true, - applet: true, - area: true, - article: true, - aside: true, - audio: true, - b: true, - base: true, - bdi: true, - bdo: true, - big: true, - blockquote: true, - body: true, - br: true, - button: true, - canvas: true, - caption: true, - circle: true, - cite: true, - code: true, - col: true, - colgroup: true, - command: true, - data: true, - datalist: true, - dd: true, - defs: true, - del: true, - details: true, - dfn: true, - dialog: true, - div: true, - dl: true, - dt: true, - ellipse: true, - em: true, - embed: true, - fieldset: true, - figcaption: true, - figure: true, - footer: true, - form: true, - g: true, - h1: true, - h2: true, - h3: true, - h4: true, - h5: true, - h6: true, - head: true, - header: true, - hgroup: true, - hr: true, - html: true, - i: true, - iframe: true, - img: true, - input: true, - ins: true, - kbd: true, - keygen: true, - label: true, - legend: true, - li: true, - line: true, - linearGradient: true, - link: true, - main: true, - map: true, - mark: true, - marquee: true, - mask: false, - menu: true, - menuitem: true, - meta: true, - meter: true, - nav: true, - noscript: true, - object: true, - ol: true, - optgroup: true, - option: true, - output: true, - p: true, - param: true, - path: true, - pattern: false, - picture: true, - polygon: true, - polyline: true, - pre: true, - progress: true, - q: true, - radialGradient: true, - rect: true, - rp: true, - rt: true, - ruby: true, - s: true, - samp: true, - script: true, - section: true, - select: true, - small: true, - source: true, - span: true, - stop: true, - strong: true, - style: true, - sub: true, - summary: true, - sup: true, - svg: true, - table: true, - tbody: true, - td: true, - text: true, - textarea: true, - tfoot: true, - th: true, - thead: true, - time: true, - title: true, - tr: true, - track: true, - tspan: true, - u: true, - ul: true, - 'var': true, - video: true, - wbr: true -}; - -function renderXJSLiteral(object, isLast, state, start, end) { - var lines = object.value.split(/\r\n|\n|\r/); - - if (start) { - utils.append(start, state); - } - - var lastNonEmptyLine = 0; - - lines.forEach(function (line, index) { - if (line.match(/[^ \t]/)) { - lastNonEmptyLine = index; - } - }); - - lines.forEach(function (line, index) { - var isFirstLine = index === 0; - var isLastLine = index === lines.length - 1; - var isLastNonEmptyLine = index === lastNonEmptyLine; - - // replace rendered whitespace tabs with spaces - var trimmedLine = line.replace(/\t/g, ' '); - - // trim whitespace touching a newline - if (!isFirstLine) { - trimmedLine = trimmedLine.replace(/^[ ]+/, ''); - } - if (!isLastLine) { - trimmedLine = trimmedLine.replace(/[ ]+$/, ''); - } - - if (!isFirstLine) { - utils.append(line.match(/^[ \t]*/)[0], state); - } - - if (trimmedLine || isLastNonEmptyLine) { - utils.append( - JSON.stringify(trimmedLine) + - (!isLastNonEmptyLine ? " + ' ' +" : ''), - state); - - if (isLastNonEmptyLine) { - if (end) { - utils.append(end, state); - } - if (!isLast) { - utils.append(', ', state); - } - } - - // only restore tail whitespace if line had literals - if (trimmedLine && !isLastLine) { - utils.append(line.match(/[ \t]*$/)[0], state); - } - } - - if (!isLastLine) { - utils.append('\n', state); - } - }); - - utils.move(object.range[1], state); -} - -function renderXJSExpressionContainer(traverse, object, isLast, path, state) { - // Plus 1 to skip `{`. - utils.move(object.range[0] + 1, state); - traverse(object.expression, path, state); - if (!isLast && object.expression.type !== Syntax.XJSEmptyExpression) { - // If we need to append a comma, make sure to do so after the expression. - utils.catchup(object.expression.range[1], state, trimLeft); - utils.append(', ', state); - } - - // Minus 1 to skip `}`. - utils.catchup(object.range[1] - 1, state, trimLeft); - utils.move(object.range[1], state); - return false; -} - -function quoteAttrName(attr) { - // Quote invalid JS identifiers. - if (!/^[a-z_$][a-z\d_$]*$/i.test(attr)) { - return '"' + attr + '"'; - } - return attr; -} - -function trimLeft(value) { - return value.replace(/^[ ]+/, ''); -} - -exports.knownTags = knownTags; -exports.renderXJSExpressionContainer = renderXJSExpressionContainer; -exports.renderXJSLiteral = renderXJSLiteral; -exports.quoteAttrName = quoteAttrName; -exports.trimLeft = trimLeft; +'use strict'; -},{"jstransform":21,"jstransform/src/utils":22}],37:[function(_dereq_,module,exports){ -/*global exports:true*/ -var es6ArrowFunctions = _dereq_('jstransform/visitors/es6-arrow-function-visitors'); +var es6ArrowFunctions = + _dereq_('jstransform/visitors/es6-arrow-function-visitors'); var es6Classes = _dereq_('jstransform/visitors/es6-class-visitors'); -var es6Destructuring = _dereq_('jstransform/visitors/es6-destructuring-visitors'); -var es6ObjectConciseMethod = _dereq_('jstransform/visitors/es6-object-concise-method-visitors'); -var es6ObjectShortNotation = _dereq_('jstransform/visitors/es6-object-short-notation-visitors'); +var es6Destructuring = + _dereq_('jstransform/visitors/es6-destructuring-visitors'); +var es6ObjectConciseMethod = + _dereq_('jstransform/visitors/es6-object-concise-method-visitors'); +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 es6CallSpread = + _dereq_('jstransform/visitors/es6-call-spread-visitors'); +var es7SpreadProperty = + _dereq_('jstransform/visitors/es7-spread-property-visitors'); var react = _dereq_('./transforms/react'); var reactDisplayName = _dereq_('./transforms/reactDisplayName'); +var reservedWords = _dereq_('jstransform/visitors/reserved-words-visitors'); /** * Map from transformName => orderedListOfVisitors. @@ -15111,8 +15799,10 @@ var transformVisitors = { 'es6-object-short-notation': es6ObjectShortNotation.visitorList, 'es6-rest-params': es6RestParameters.visitorList, 'es6-templates': es6Templates.visitorList, + 'es6-call-spread': es6CallSpread.visitorList, 'es7-spread-property': es7SpreadProperty.visitorList, - 'react': react.visitorList.concat(reactDisplayName.visitorList) + 'react': react.visitorList.concat(reactDisplayName.visitorList), + 'reserved-words': reservedWords.visitorList }; var transformSets = { @@ -15124,8 +15814,12 @@ var transformSets = { 'es6-rest-params', 'es6-templates', 'es6-destructuring', + 'es6-call-spread', 'es7-spread-property' ], + 'es3': [ + 'reserved-words' + ], 'react': [ 'react' ] @@ -15135,6 +15829,7 @@ var transformSets = { * Specifies the order in which each transform should run. */ var transformRunOrder = [ + 'reserved-words', 'es6-arrow-functions', 'es6-object-concise-method', 'es6-object-short-notation', @@ -15142,6 +15837,7 @@ var transformRunOrder = [ 'es6-rest-params', 'es6-templates', 'es6-destructuring', + 'es6-call-spread', 'es7-spread-property', 'react' ]; @@ -15195,5 +15891,34 @@ exports.getVisitorsBySet = getVisitorsBySet; exports.getAllVisitors = getAllVisitors; exports.transformVisitors = transformVisitors; -},{"./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) +},{"./transforms/react":38,"./transforms/reactDisplayName":39,"jstransform/visitors/es6-arrow-function-visitors":24,"jstransform/visitors/es6-call-spread-visitors":25,"jstransform/visitors/es6-class-visitors":26,"jstransform/visitors/es6-destructuring-visitors":27,"jstransform/visitors/es6-object-concise-method-visitors":28,"jstransform/visitors/es6-object-short-notation-visitors":29,"jstransform/visitors/es6-rest-param-visitors":30,"jstransform/visitors/es6-template-visitors":31,"jstransform/visitors/es7-spread-property-visitors":33,"jstransform/visitors/reserved-words-visitors":35}],41:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, 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. + */ + +'use strict'; +/*eslint-disable no-undef*/ +var Buffer = _dereq_('buffer').Buffer; + +function inlineSourceMap(sourceMap, sourceCode, sourceFilename) { + // This can be used with a sourcemap that has already has toJSON called on it. + // Check first. + var json = sourceMap; + if (typeof sourceMap.toJSON === 'function') { + json = sourceMap.toJSON(); + } + json.sources = [sourceFilename]; + json.sourcesContent = [sourceCode]; + var base64 = Buffer(JSON.stringify(json)).toString('base64'); + return '//# sourceMappingURL=data:application/json;base64,' + base64; +} + +module.exports = inlineSourceMap; + +},{"buffer":3}]},{},[1])(1) }); \ No newline at end of file diff --git a/src/React.Core/Resources/react-with-addons.js b/src/React.Core/Resources/react-with-addons.js index cdba5d224..ceff91b31 100644 --- a/src/React.Core/Resources/react-with-addons.js +++ b/src/React.Core/Resources/react-with-addons.js @@ -1,9 +1,9 @@ /** - * React (with addons) v0.12.2 + * React (with addons) v0.13.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);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 8 && documentMode <= 11) + ) ); /** @@ -139,12 +170,51 @@ var eventTypes = { topLevelTypes.topTextInput, topLevelTypes.topPaste ] + }, + compositionEnd: { + phasedRegistrationNames: { + bubbled: keyOf({onCompositionEnd: null}), + captured: keyOf({onCompositionEndCapture: null}) + }, + dependencies: [ + topLevelTypes.topBlur, + topLevelTypes.topCompositionEnd, + topLevelTypes.topKeyDown, + topLevelTypes.topKeyPress, + topLevelTypes.topKeyUp, + topLevelTypes.topMouseDown + ] + }, + compositionStart: { + phasedRegistrationNames: { + bubbled: keyOf({onCompositionStart: null}), + captured: keyOf({onCompositionStartCapture: null}) + }, + dependencies: [ + topLevelTypes.topBlur, + topLevelTypes.topCompositionStart, + topLevelTypes.topKeyDown, + topLevelTypes.topKeyPress, + topLevelTypes.topKeyUp, + topLevelTypes.topMouseDown + ] + }, + compositionUpdate: { + phasedRegistrationNames: { + bubbled: keyOf({onCompositionUpdate: null}), + captured: keyOf({onCompositionUpdateCapture: null}) + }, + dependencies: [ + topLevelTypes.topBlur, + topLevelTypes.topCompositionUpdate, + topLevelTypes.topKeyDown, + topLevelTypes.topKeyPress, + topLevelTypes.topKeyUp, + topLevelTypes.topMouseDown + ] } }; -// 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; @@ -161,6 +231,297 @@ function isKeypressCommand(nativeEvent) { ); } + +/** + * Translate native top level events into event types. + * + * @param {string} topLevelType + * @return {object} + */ +function getCompositionEventType(topLevelType) { + switch (topLevelType) { + case topLevelTypes.topCompositionStart: + return eventTypes.compositionStart; + case topLevelTypes.topCompositionEnd: + return eventTypes.compositionEnd; + case topLevelTypes.topCompositionUpdate: + return eventTypes.compositionUpdate; + } +} + +/** + * Does our fallback best-guess model think this event signifies that + * composition has begun? + * + * @param {string} topLevelType + * @param {object} nativeEvent + * @return {boolean} + */ +function isFallbackCompositionStart(topLevelType, nativeEvent) { + return ( + topLevelType === topLevelTypes.topKeyDown && + nativeEvent.keyCode === START_KEYCODE + ); +} + +/** + * Does our fallback mode think that this event is the end of composition? + * + * @param {string} topLevelType + * @param {object} nativeEvent + * @return {boolean} + */ +function isFallbackCompositionEnd(topLevelType, nativeEvent) { + switch (topLevelType) { + case topLevelTypes.topKeyUp: + // Command keys insert or clear IME input. + return (END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1); + case topLevelTypes.topKeyDown: + // Expect IME keyCode on each keydown. If we get any other + // code we must have exited earlier. + return (nativeEvent.keyCode !== START_KEYCODE); + case topLevelTypes.topKeyPress: + case topLevelTypes.topMouseDown: + case topLevelTypes.topBlur: + // Events are not possible without cancelling IME. + return true; + default: + return false; + } +} + +/** + * Google Input Tools provides composition data via a CustomEvent, + * with the `data` property populated in the `detail` object. If this + * is available on the event object, use it. If not, this is a plain + * composition event and we have nothing special to extract. + * + * @param {object} nativeEvent + * @return {?string} + */ +function getDataFromCustomEvent(nativeEvent) { + var detail = nativeEvent.detail; + if (typeof detail === 'object' && 'data' in detail) { + return detail.data; + } + return null; +} + +// Track the current IME composition fallback object, if any. +var currentComposition = null; + +/** + * @param {string} topLevelType Record from `EventConstants`. + * @param {DOMEventTarget} topLevelTarget The listening component root node. + * @param {string} topLevelTargetID ID of `topLevelTarget`. + * @param {object} nativeEvent Native browser event. + * @return {?object} A SyntheticCompositionEvent. + */ +function extractCompositionEvent( + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent +) { + var eventType; + var fallbackData; + + if (canUseCompositionEvent) { + eventType = getCompositionEventType(topLevelType); + } else if (!currentComposition) { + if (isFallbackCompositionStart(topLevelType, nativeEvent)) { + eventType = eventTypes.compositionStart; + } + } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) { + eventType = eventTypes.compositionEnd; + } + + if (!eventType) { + return null; + } + + if (useFallbackCompositionData) { + // The current composition is stored statically and must not be + // overwritten while composition continues. + if (!currentComposition && eventType === eventTypes.compositionStart) { + currentComposition = FallbackCompositionState.getPooled(topLevelTarget); + } else if (eventType === eventTypes.compositionEnd) { + if (currentComposition) { + fallbackData = currentComposition.getData(); + } + } + } + + var event = SyntheticCompositionEvent.getPooled( + eventType, + topLevelTargetID, + nativeEvent + ); + + if (fallbackData) { + // Inject data generated from fallback path into the synthetic event. + // This matches the property of native CompositionEventInterface. + event.data = fallbackData; + } else { + var customData = getDataFromCustomEvent(nativeEvent); + if (customData !== null) { + event.data = customData; + } + } + + EventPropagators.accumulateTwoPhaseDispatches(event); + return event; +} + +/** + * @param {string} topLevelType Record from `EventConstants`. + * @param {object} nativeEvent Native browser event. + * @return {?string} The string corresponding to this `beforeInput` event. + */ +function getNativeBeforeInputChars(topLevelType, nativeEvent) { + switch (topLevelType) { + case topLevelTypes.topCompositionEnd: + return getDataFromCustomEvent(nativeEvent); + case topLevelTypes.topKeyPress: + /** + * If native `textInput` events are available, our goal is to make + * use of them. However, there is a special case: the spacebar key. + * In Webkit, preventing default on a spacebar `textInput` event + * cancels character insertion, but it *also* causes the browser + * to fall back to its default spacebar behavior of scrolling the + * page. + * + * Tracking at: + * https://code.google.com/p/chromium/issues/detail?id=355103 + * + * To avoid this issue, use the keypress event as if no `textInput` + * event is available. + */ + var which = nativeEvent.which; + if (which !== SPACEBAR_CODE) { + return null; + } + + hasSpaceKeypress = true; + return SPACEBAR_CHAR; + + case topLevelTypes.topTextInput: + // Record the characters to be added to the DOM. + var chars = nativeEvent.data; + + // If it's a spacebar character, assume that we have already handled + // 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 null; + } + + return chars; + + default: + // For other native event types, do nothing. + return null; + } +} + +/** + * For browsers that do not provide the `textInput` event, extract the + * appropriate string to use for SyntheticInputEvent. + * + * @param {string} topLevelType Record from `EventConstants`. + * @param {object} nativeEvent Native browser event. + * @return {?string} The fallback string for this `beforeInput` event. + */ +function getFallbackBeforeInputChars(topLevelType, nativeEvent) { + // If we are currently composing (IME) and using a fallback to do so, + // try to extract the composed characters from the fallback object. + if (currentComposition) { + if ( + topLevelType === topLevelTypes.topCompositionEnd || + isFallbackCompositionEnd(topLevelType, nativeEvent) + ) { + var chars = currentComposition.getData(); + FallbackCompositionState.release(currentComposition); + currentComposition = null; + return chars; + } + return null; + } + + switch (topLevelType) { + case topLevelTypes.topPaste: + // If a paste event occurs after a keypress, throw out the input + // chars. Paste events should not lead to BeforeInput events. + return null; + case topLevelTypes.topKeyPress: + /** + * As of v27, Firefox may fire keypress events even when no character + * will be inserted. A few possibilities: + * + * - `which` is `0`. Arrow keys, Esc key, etc. + * + * - `which` is the pressed key code, but no char is available. + * Ex: 'AltGr + d` in Polish. There is no modified character for + * this key combination and no character is inserted into the + * document, but FF fires the keypress for char code `100` anyway. + * No `input` event will occur. + * + * - `which` is the pressed key code, but a command combination is + * being used. Ex: `Cmd+C`. No character is inserted, and no + * `input` event will occur. + */ + if (nativeEvent.which && !isKeypressCommand(nativeEvent)) { + return String.fromCharCode(nativeEvent.which); + } + return null; + case topLevelTypes.topCompositionEnd: + return useFallbackCompositionData ? null : nativeEvent.data; + default: + return null; + } +} + +/** + * Extract a SyntheticInputEvent for `beforeInput`, based on either native + * `textInput` or fallback behavior. + * + * @param {string} topLevelType Record from `EventConstants`. + * @param {DOMEventTarget} topLevelTarget The listening component root node. + * @param {string} topLevelTargetID ID of `topLevelTarget`. + * @param {object} nativeEvent Native browser event. + * @return {?object} A SyntheticInputEvent. + */ +function extractBeforeInputEvent( + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent +) { + var chars; + + if (canUseTextInputEvent) { + chars = getNativeBeforeInputChars(topLevelType, nativeEvent); + } else { + chars = getFallbackBeforeInputChars(topLevelType, nativeEvent); + } + + // If no characters are being inserted, no BeforeInput event should + // be fired. + if (!chars) { + return null; + } + + var event = SyntheticInputEvent.getPooled( + eventTypes.beforeInput, + topLevelTargetID, + nativeEvent + ); + + event.data = chars; + EventPropagators.accumulateTwoPhaseDispatches(event); + return event; +} + /** * Create an `onBeforeInput` event to match * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents. @@ -174,6 +535,10 @@ function isKeypressCommand(nativeEvent) { * actually been added, contrary to the spec. Thus, `textInput` is the best * available event to identify the characters that have actually been inserted * into the target node. + * + * This plugin is also responsible for emitting `composition` events, thus + * allowing us to share composition fallback code for both `beforeInput` and + * `composition` event types. */ var BeforeInputEventPlugin = { @@ -188,144 +553,54 @@ var BeforeInputEventPlugin = { * @see {EventPluginHub.extractEvents} */ extractEvents: function( - topLevelType, - topLevelTarget, - topLevelTargetID, - nativeEvent) { + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent + ) { + return [ + extractCompositionEvent( + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent + ), + extractBeforeInputEvent( + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent + ) + ]; + } +}; - var chars; - - if (canUseTextInputEvent) { - switch (topLevelType) { - case topLevelTypes.topKeyPress: - /** - * If native `textInput` events are available, our goal is to make - * use of them. However, there is a special case: the spacebar key. - * In Webkit, preventing default on a spacebar `textInput` event - * cancels character insertion, but it *also* causes the browser - * to fall back to its default spacebar behavior of scrolling the - * page. - * - * Tracking at: - * https://code.google.com/p/chromium/issues/detail?id=355103 - * - * To avoid this issue, use the keypress event as if no `textInput` - * event is available. - */ - var which = nativeEvent.which; - if (which !== SPACEBAR_CODE) { - return; - } +module.exports = BeforeInputEventPlugin; - hasSpaceKeypress = true; - chars = SPACEBAR_CHAR; - break; +},{"106":106,"110":110,"157":157,"16":16,"21":21,"22":22,"23":23}],4:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, 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 CSSCore + * @typechecks + */ - case topLevelTypes.topTextInput: - // Record the characters to be added to the DOM. - chars = nativeEvent.data; +var invariant = _dereq_(150); - // If it's a spacebar character, assume that we have already handled - // 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; - } +/** + * The CSSCore module specifies the API (and implements most of the methods) + * that should be used when dealing with the display of elements (via their + * CSS classes and visibility on screen. It is an API focused on mutating the + * display and not reading it as no logical state should be encoded in the + * display of elements. + */ - // Otherwise, carry on. - break; - - default: - // For other native event types, do nothing. - return; - } - } else { - switch (topLevelType) { - case topLevelTypes.topPaste: - // If a paste event occurs after a keypress, throw out the input - // chars. Paste events should not lead to BeforeInput events. - fallbackChars = null; - break; - case topLevelTypes.topKeyPress: - /** - * As of v27, Firefox may fire keypress events even when no character - * will be inserted. A few possibilities: - * - * - `which` is `0`. Arrow keys, Esc key, etc. - * - * - `which` is the pressed key code, but no char is available. - * Ex: 'AltGr + d` in Polish. There is no modified character for - * this key combination and no character is inserted into the - * document, but FF fires the keypress for char code `100` anyway. - * No `input` event will occur. - * - * - `which` is the pressed key code, but a command combination is - * being used. Ex: `Cmd+C`. No character is inserted, and no - * `input` event will occur. - */ - if (nativeEvent.which && !isKeypressCommand(nativeEvent)) { - fallbackChars = String.fromCharCode(nativeEvent.which); - } - break; - case topLevelTypes.topCompositionEnd: - fallbackChars = nativeEvent.data; - break; - } - - // If no changes have occurred to the fallback string, no relevant - // event has fired and we're done. - if (fallbackChars === null) { - return; - } - - chars = fallbackChars; - } - - // If no characters are being inserted, no BeforeInput event should - // be fired. - if (!chars) { - return; - } - - var event = SyntheticInputEvent.getPooled( - eventTypes.beforeInput, - topLevelTargetID, - nativeEvent - ); - - event.data = chars; - fallbackChars = null; - EventPropagators.accumulateTwoPhaseDispatches(event); - return event; - } -}; - -module.exports = BeforeInputEventPlugin; - -},{"./EventConstants":17,"./EventPropagators":22,"./ExecutionEnvironment":23,"./SyntheticInputEvent":101,"./keyOf":147}],4:[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 CSSCore - * @typechecks - */ - -var invariant = _dereq_("./invariant"); - -/** - * The CSSCore module specifies the API (and implements most of the methods) - * that should be used when dealing with the display of elements (via their - * CSS classes and visibility on screen. It is an API focused on mutating the - * display and not reading it as no logical state should be encoded in the - * display of elements. - */ - -var CSSCore = { +var CSSCore = { /** * Adds the class passed in to the element if it doesn't already have it. @@ -412,9 +687,9 @@ var CSSCore = { module.exports = CSSCore; -},{"./invariant":140}],5:[function(_dereq_,module,exports){ +},{"150":150}],5:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -424,12 +699,14 @@ module.exports = CSSCore; * @providesModule CSSProperty */ -"use strict"; +'use strict'; /** * CSS properties which accept numbers but are not in units of "px". */ var isUnitlessNumber = { + boxFlex: true, + boxFlexGroup: true, columnCount: true, flex: true, flexGrow: true, @@ -533,7 +810,7 @@ module.exports = CSSProperty; },{}],6:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -544,16 +821,16 @@ module.exports = CSSProperty; * @typechecks static-only */ -"use strict"; +'use strict'; -var CSSProperty = _dereq_("./CSSProperty"); -var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); +var CSSProperty = _dereq_(5); +var ExecutionEnvironment = _dereq_(22); -var camelizeStyleName = _dereq_("./camelizeStyleName"); -var dangerousStyleValue = _dereq_("./dangerousStyleValue"); -var hyphenateStyleName = _dereq_("./hyphenateStyleName"); -var memoizeStringOnly = _dereq_("./memoizeStringOnly"); -var warning = _dereq_("./warning"); +var camelizeStyleName = _dereq_(121); +var dangerousStyleValue = _dereq_(128); +var hyphenateStyleName = _dereq_(148); +var memoizeStringOnly = _dereq_(159); +var warning = _dereq_(171); var processStyleName = memoizeStringOnly(function(styleName) { return hyphenateStyleName(styleName); @@ -568,7 +845,14 @@ if (ExecutionEnvironment.canUseDOM) { } if ("production" !== "development") { + // 'msTransform' is correct, but the other prefixes should be capitalized + var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/; + + // style values shouldn't contain a semicolon + var badStyleValueWithSemicolonPattern = /;\s*$/; + var warnedStyleNames = {}; + var warnedStyleValues = {}; var warnHyphenatedStyleName = function(name) { if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { @@ -578,10 +862,54 @@ if ("production" !== "development") { warnedStyleNames[name] = true; ("production" !== "development" ? warning( false, - 'Unsupported style property ' + name + '. Did you mean ' + - camelizeStyleName(name) + '?' + 'Unsupported style property %s. Did you mean %s?', + name, + camelizeStyleName(name) + ) : null); + }; + + var warnBadVendoredStyleName = function(name) { + if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { + return; + } + + warnedStyleNames[name] = true; + ("production" !== "development" ? warning( + false, + 'Unsupported vendor-prefixed style property %s. Did you mean %s?', + name, + name.charAt(0).toUpperCase() + name.slice(1) + ) : null); + }; + + var warnStyleValueWithSemicolon = function(name, value) { + if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) { + return; + } + + warnedStyleValues[value] = true; + ("production" !== "development" ? warning( + false, + 'Style property values shouldn\'t contain a semicolon. ' + + 'Try "%s: %s" instead.', + name, + value.replace(badStyleValueWithSemicolonPattern, '') ) : null); }; + + /** + * @param {string} name + * @param {*} value + */ + var warnValidStyle = function(name, value) { + if (name.indexOf('-') > -1) { + warnHyphenatedStyleName(name); + } else if (badVendoredStyleNamePattern.test(name)) { + warnBadVendoredStyleName(name); + } else if (badStyleValueWithSemicolonPattern.test(value)) { + warnStyleValueWithSemicolon(name, value); + } + }; } /** @@ -607,12 +935,10 @@ var CSSPropertyOperations = { if (!styles.hasOwnProperty(styleName)) { continue; } + var styleValue = styles[styleName]; if ("production" !== "development") { - if (styleName.indexOf('-') > -1) { - warnHyphenatedStyleName(styleName); - } + warnValidStyle(styleName, styleValue); } - var styleValue = styles[styleName]; if (styleValue != null) { serialized += processStyleName(styleName) + ':'; serialized += dangerousStyleValue(styleName, styleValue) + ';'; @@ -635,9 +961,7 @@ var CSSPropertyOperations = { continue; } if ("production" !== "development") { - if (styleName.indexOf('-') > -1) { - warnHyphenatedStyleName(styleName); - } + warnValidStyle(styleName, styles[styleName]); } var styleValue = dangerousStyleValue(styleName, styles[styleName]); if (styleName === 'float') { @@ -664,9 +988,9 @@ var CSSPropertyOperations = { module.exports = CSSPropertyOperations; -},{"./CSSProperty":5,"./ExecutionEnvironment":23,"./camelizeStyleName":112,"./dangerousStyleValue":119,"./hyphenateStyleName":138,"./memoizeStringOnly":149,"./warning":160}],7:[function(_dereq_,module,exports){ +},{"121":121,"128":128,"148":148,"159":159,"171":171,"22":22,"5":5}],7:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -676,12 +1000,12 @@ module.exports = CSSPropertyOperations; * @providesModule CallbackQueue */ -"use strict"; +'use strict'; -var PooledClass = _dereq_("./PooledClass"); +var PooledClass = _dereq_(30); -var assign = _dereq_("./Object.assign"); -var invariant = _dereq_("./invariant"); +var assign = _dereq_(29); +var invariant = _dereq_(150); /** * A specialized pseudo-event module to help keep track of components waiting to @@ -727,7 +1051,7 @@ assign(CallbackQueue.prototype, { if (callbacks) { ("production" !== "development" ? invariant( callbacks.length === contexts.length, - "Mismatched list of contexts in callback queue" + 'Mismatched list of contexts in callback queue' ) : invariant(callbacks.length === contexts.length)); this._callbacks = null; this._contexts = null; @@ -762,9 +1086,9 @@ PooledClass.addPoolingTo(CallbackQueue); module.exports = CallbackQueue; -},{"./Object.assign":29,"./PooledClass":30,"./invariant":140}],8:[function(_dereq_,module,exports){ +},{"150":150,"29":29,"30":30}],8:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -774,18 +1098,18 @@ module.exports = CallbackQueue; * @providesModule ChangeEventPlugin */ -"use strict"; +'use strict'; -var EventConstants = _dereq_("./EventConstants"); -var EventPluginHub = _dereq_("./EventPluginHub"); -var EventPropagators = _dereq_("./EventPropagators"); -var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); -var ReactUpdates = _dereq_("./ReactUpdates"); -var SyntheticEvent = _dereq_("./SyntheticEvent"); +var EventConstants = _dereq_(16); +var EventPluginHub = _dereq_(18); +var EventPropagators = _dereq_(21); +var ExecutionEnvironment = _dereq_(22); +var ReactUpdates = _dereq_(100); +var SyntheticEvent = _dereq_(108); -var isEventSupported = _dereq_("./isEventSupported"); -var isTextInputElement = _dereq_("./isTextInputElement"); -var keyOf = _dereq_("./keyOf"); +var isEventSupported = _dereq_(151); +var isTextInputElement = _dereq_(153); +var keyOf = _dereq_(157); var topLevelTypes = EventConstants.topLevelTypes; @@ -830,7 +1154,7 @@ var doesChangeEventBubble = false; if (ExecutionEnvironment.canUseDOM) { // See `handleChange` comment below doesChangeEventBubble = isEventSupported('change') && ( - !('documentMode' in document) || document.documentMode > 8 + (!('documentMode' in document) || document.documentMode > 8) ); } @@ -907,7 +1231,7 @@ if (ExecutionEnvironment.canUseDOM) { // IE9 claims to support the input event but fails to trigger it when // deleting text, so we ignore its input events isInputEventSupported = isEventSupported('input') && ( - !('documentMode' in document) || document.documentMode > 9 + (!('documentMode' in document) || document.documentMode > 9) ); } @@ -1144,9 +1468,9 @@ var ChangeEventPlugin = { module.exports = ChangeEventPlugin; -},{"./EventConstants":17,"./EventPluginHub":19,"./EventPropagators":22,"./ExecutionEnvironment":23,"./ReactUpdates":91,"./SyntheticEvent":99,"./isEventSupported":141,"./isTextInputElement":143,"./keyOf":147}],9:[function(_dereq_,module,exports){ +},{"100":100,"108":108,"151":151,"153":153,"157":157,"16":16,"18":18,"21":21,"22":22}],9:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -1157,7 +1481,7 @@ module.exports = ChangeEventPlugin; * @typechecks */ -"use strict"; +'use strict'; var nextReactRootIndex = 0; @@ -1171,358 +1495,60 @@ module.exports = ClientReactRootIndex; },{}],10:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, 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 CompositionEventPlugin + * @providesModule DOMChildrenOperations * @typechecks static-only */ -"use strict"; - -var EventConstants = _dereq_("./EventConstants"); -var EventPropagators = _dereq_("./EventPropagators"); -var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); -var ReactInputSelection = _dereq_("./ReactInputSelection"); -var SyntheticCompositionEvent = _dereq_("./SyntheticCompositionEvent"); - -var getTextContentAccessor = _dereq_("./getTextContentAccessor"); -var keyOf = _dereq_("./keyOf"); - -var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space -var START_KEYCODE = 229; - -var useCompositionEvent = ( - ExecutionEnvironment.canUseDOM && - 'CompositionEvent' in window -); - -// In IE9+, we have access to composition events, but the data supplied -// by the native compositionend event may be incorrect. In Korean, for example, -// the compositionend event contains only one character regardless of -// how many characters have been composed since compositionstart. -// We therefore use the fallback data while still using the native -// events as triggers. -var useFallbackData = ( - !useCompositionEvent || - ( - 'documentMode' in document && - document.documentMode > 8 && - document.documentMode <= 11 - ) -); - -var topLevelTypes = EventConstants.topLevelTypes; -var currentComposition = null; +'use strict'; -// Events and their corresponding property names. -var eventTypes = { - compositionEnd: { - phasedRegistrationNames: { - bubbled: keyOf({onCompositionEnd: null}), - captured: keyOf({onCompositionEndCapture: null}) - }, - dependencies: [ - topLevelTypes.topBlur, - topLevelTypes.topCompositionEnd, - topLevelTypes.topKeyDown, - topLevelTypes.topKeyPress, - topLevelTypes.topKeyUp, - topLevelTypes.topMouseDown - ] - }, - compositionStart: { - phasedRegistrationNames: { - bubbled: keyOf({onCompositionStart: null}), - captured: keyOf({onCompositionStartCapture: null}) - }, - dependencies: [ - topLevelTypes.topBlur, - topLevelTypes.topCompositionStart, - topLevelTypes.topKeyDown, - topLevelTypes.topKeyPress, - topLevelTypes.topKeyUp, - topLevelTypes.topMouseDown - ] - }, - compositionUpdate: { - phasedRegistrationNames: { - bubbled: keyOf({onCompositionUpdate: null}), - captured: keyOf({onCompositionUpdateCapture: null}) - }, - dependencies: [ - topLevelTypes.topBlur, - topLevelTypes.topCompositionUpdate, - topLevelTypes.topKeyDown, - topLevelTypes.topKeyPress, - topLevelTypes.topKeyUp, - topLevelTypes.topMouseDown - ] - } -}; +var Danger = _dereq_(13); +var ReactMultiChildUpdateTypes = _dereq_(79); -/** - * Translate native top level events into event types. - * - * @param {string} topLevelType - * @return {object} - */ -function getCompositionEventType(topLevelType) { - switch (topLevelType) { - case topLevelTypes.topCompositionStart: - return eventTypes.compositionStart; - case topLevelTypes.topCompositionEnd: - return eventTypes.compositionEnd; - case topLevelTypes.topCompositionUpdate: - return eventTypes.compositionUpdate; - } -} +var setTextContent = _dereq_(165); +var invariant = _dereq_(150); /** - * Does our fallback best-guess model think this event signifies that - * composition has begun? + * Inserts `childNode` as a child of `parentNode` at the `index`. * - * @param {string} topLevelType - * @param {object} nativeEvent - * @return {boolean} + * @param {DOMElement} parentNode Parent node in which to insert. + * @param {DOMElement} childNode Child node to insert. + * @param {number} index Index at which to insert the child. + * @internal */ -function isFallbackStart(topLevelType, nativeEvent) { - return ( - topLevelType === topLevelTypes.topKeyDown && - nativeEvent.keyCode === START_KEYCODE +function insertChildAt(parentNode, childNode, index) { + // By exploiting arrays returning `undefined` for an undefined index, we can + // rely exclusively on `insertBefore(node, null)` instead of also using + // `appendChild(node)`. However, using `undefined` is not allowed by all + // browsers so we must replace it with `null`. + parentNode.insertBefore( + childNode, + parentNode.childNodes[index] || null ); } /** - * Does our fallback mode think that this event is the end of composition? - * - * @param {string} topLevelType - * @param {object} nativeEvent - * @return {boolean} - */ -function isFallbackEnd(topLevelType, nativeEvent) { - switch (topLevelType) { - case topLevelTypes.topKeyUp: - // Command keys insert or clear IME input. - return (END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1); - case topLevelTypes.topKeyDown: - // Expect IME keyCode on each keydown. If we get any other - // code we must have exited earlier. - return (nativeEvent.keyCode !== START_KEYCODE); - case topLevelTypes.topKeyPress: - case topLevelTypes.topMouseDown: - case topLevelTypes.topBlur: - // Events are not possible without cancelling IME. - return true; - default: - return false; - } -} - -/** - * Helper class stores information about selection and document state - * so we can figure out what changed at a later date. - * - * @param {DOMEventTarget} root - */ -function FallbackCompositionState(root) { - this.root = root; - this.startSelection = ReactInputSelection.getSelection(root); - this.startValue = this.getText(); -} - -/** - * Get current text of input. - * - * @return {string} - */ -FallbackCompositionState.prototype.getText = function() { - return this.root.value || this.root[getTextContentAccessor()]; -}; - -/** - * Text that has changed since the start of composition. - * - * @return {string} + * Operations for updating with DOM children. */ -FallbackCompositionState.prototype.getData = function() { - var endValue = this.getText(); - var prefixLength = this.startSelection.start; - var suffixLength = this.startValue.length - this.startSelection.end; - - return endValue.substr( - prefixLength, - endValue.length - suffixLength - prefixLength - ); -}; +var DOMChildrenOperations = { -/** - * This plugin creates `onCompositionStart`, `onCompositionUpdate` and - * `onCompositionEnd` events on inputs, textareas and contentEditable - * nodes. - */ -var CompositionEventPlugin = { + dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup, - eventTypes: eventTypes, + updateTextContent: setTextContent, /** - * @param {string} topLevelType Record from `EventConstants`. - * @param {DOMEventTarget} topLevelTarget The listening component root node. - * @param {string} topLevelTargetID ID of `topLevelTarget`. - * @param {object} nativeEvent Native browser event. - * @return {*} An accumulation of synthetic events. - * @see {EventPluginHub.extractEvents} - */ - extractEvents: function( - topLevelType, - topLevelTarget, - topLevelTargetID, - nativeEvent) { - - var eventType; - var data; - - if (useCompositionEvent) { - eventType = getCompositionEventType(topLevelType); - } else if (!currentComposition) { - if (isFallbackStart(topLevelType, nativeEvent)) { - eventType = eventTypes.compositionStart; - } - } else if (isFallbackEnd(topLevelType, nativeEvent)) { - eventType = eventTypes.compositionEnd; - } - - if (useFallbackData) { - // The current composition is stored statically and must not be - // overwritten while composition continues. - if (!currentComposition && eventType === eventTypes.compositionStart) { - currentComposition = new FallbackCompositionState(topLevelTarget); - } else if (eventType === eventTypes.compositionEnd) { - if (currentComposition) { - data = currentComposition.getData(); - currentComposition = null; - } - } - } - - if (eventType) { - var event = SyntheticCompositionEvent.getPooled( - eventType, - topLevelTargetID, - nativeEvent - ); - if (data) { - // Inject data generated from fallback path into the synthetic event. - // This matches the property of native CompositionEventInterface. - event.data = data; - } - EventPropagators.accumulateTwoPhaseDispatches(event); - return event; - } - } -}; - -module.exports = CompositionEventPlugin; - -},{"./EventConstants":17,"./EventPropagators":22,"./ExecutionEnvironment":23,"./ReactInputSelection":65,"./SyntheticCompositionEvent":97,"./getTextContentAccessor":135,"./keyOf":147}],11:[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 DOMChildrenOperations - * @typechecks static-only - */ - -"use strict"; - -var Danger = _dereq_("./Danger"); -var ReactMultiChildUpdateTypes = _dereq_("./ReactMultiChildUpdateTypes"); - -var getTextContentAccessor = _dereq_("./getTextContentAccessor"); -var invariant = _dereq_("./invariant"); - -/** - * The DOM property to use when setting text content. - * - * @type {string} - * @private - */ -var textContentAccessor = getTextContentAccessor(); - -/** - * Inserts `childNode` as a child of `parentNode` at the `index`. - * - * @param {DOMElement} parentNode Parent node in which to insert. - * @param {DOMElement} childNode Child node to insert. - * @param {number} index Index at which to insert the child. - * @internal - */ -function insertChildAt(parentNode, childNode, index) { - // By exploiting arrays returning `undefined` for an undefined index, we can - // rely exclusively on `insertBefore(node, null)` instead of also using - // `appendChild(node)`. However, using `undefined` is not allowed by all - // browsers so we must replace it with `null`. - parentNode.insertBefore( - childNode, - parentNode.childNodes[index] || null - ); -} - -var updateTextContent; -if (textContentAccessor === 'textContent') { - /** - * Sets the text content of `node` to `text`. - * - * @param {DOMElement} node Node to change - * @param {string} text New text content - */ - updateTextContent = function(node, text) { - node.textContent = text; - }; -} else { - /** - * Sets the text content of `node` to `text`. - * - * @param {DOMElement} node Node to change - * @param {string} text New text content - */ - updateTextContent = function(node, text) { - // In order to preserve newlines correctly, we can't use .innerText to set - // the contents (see #1080), so we empty the element then append a text node - while (node.firstChild) { - node.removeChild(node.firstChild); - } - if (text) { - var doc = node.ownerDocument || document; - node.appendChild(doc.createTextNode(text)); - } - }; -} - -/** - * Operations for updating with DOM children. - */ -var DOMChildrenOperations = { - - dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup, - - updateTextContent: updateTextContent, - - /** - * Updates a component's children by processing a series of updates. The - * update configurations are each expected to have a `parentNode` property. - * - * @param {array} updates List of update configurations. - * @param {array} markupList List of markup strings. - * @internal + * Updates a component's children by processing a series of updates. The + * update configurations are each expected to have a `parentNode` property. + * + * @param {array} updates List of update configurations. + * @param {array} markupList List of markup strings. + * @internal */ processUpdates: function(updates, markupList) { var update; @@ -1531,7 +1557,8 @@ var DOMChildrenOperations = { // List of children that will be moved or removed. var updatedChildren = null; - for (var i = 0; update = updates[i]; i++) { + for (var i = 0; i < updates.length; i++) { + update = updates[i]; if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING || update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) { var updatedIndex = update.fromIndex; @@ -1543,7 +1570,7 @@ 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 when using tables, ' + - 'nesting tags like
,

, or , or using non-SVG elements '+ + 'nesting tags like ,

, or , or using non-SVG elements ' + 'in an parent. Try inspecting the child nodes of the element ' + 'with React ID `%s`.', updatedIndex, @@ -1568,7 +1595,8 @@ var DOMChildrenOperations = { } } - for (var k = 0; update = updates[k]; k++) { + for (var k = 0; k < updates.length; k++) { + update = updates[k]; switch (update.type) { case ReactMultiChildUpdateTypes.INSERT_MARKUP: insertChildAt( @@ -1585,7 +1613,7 @@ var DOMChildrenOperations = { ); break; case ReactMultiChildUpdateTypes.TEXT_CONTENT: - updateTextContent( + setTextContent( update.parentNode, update.textContent ); @@ -1601,9 +1629,9 @@ var DOMChildrenOperations = { module.exports = DOMChildrenOperations; -},{"./Danger":14,"./ReactMultiChildUpdateTypes":72,"./getTextContentAccessor":135,"./invariant":140}],12:[function(_dereq_,module,exports){ +},{"13":13,"150":150,"165":165,"79":79}],11:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -1616,9 +1644,9 @@ module.exports = DOMChildrenOperations; /*jslint bitwise: true */ -"use strict"; +'use strict'; -var invariant = _dereq_("./invariant"); +var invariant = _dereq_(150); function checkMask(value, bitmask) { return (value & bitmask) === bitmask; @@ -1898,9 +1926,9 @@ var DOMProperty = { module.exports = DOMProperty; -},{"./invariant":140}],13:[function(_dereq_,module,exports){ +},{"150":150}],12:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -1911,13 +1939,12 @@ module.exports = DOMProperty; * @typechecks static-only */ -"use strict"; +'use strict'; -var DOMProperty = _dereq_("./DOMProperty"); +var DOMProperty = _dereq_(11); -var escapeTextForBrowser = _dereq_("./escapeTextForBrowser"); -var memoizeStringOnly = _dereq_("./memoizeStringOnly"); -var warning = _dereq_("./warning"); +var quoteAttributeValueForBrowser = _dereq_(163); +var warning = _dereq_(171); function shouldIgnoreValue(name, value) { return value == null || @@ -1927,10 +1954,6 @@ function shouldIgnoreValue(name, value) { (DOMProperty.hasOverloadedBooleanValue[name] && value === false); } -var processAttributeNameAndPrefix = memoizeStringOnly(function(name) { - return escapeTextForBrowser(name) + '="'; -}); - if ("production" !== "development") { var reactProps = { children: true, @@ -1962,7 +1985,9 @@ if ("production" !== "development") { // logging too much when using transferPropsTo. ("production" !== "development" ? warning( standardName == null, - 'Unknown DOM property ' + name + '. Did you mean ' + standardName + '?' + 'Unknown DOM property %s. Did you mean %s?', + name, + standardName ) : null); }; @@ -1980,8 +2005,8 @@ var DOMPropertyOperations = { * @return {string} Markup string. */ createMarkupForID: function(id) { - return processAttributeNameAndPrefix(DOMProperty.ID_ATTRIBUTE_NAME) + - escapeTextForBrowser(id) + '"'; + return DOMProperty.ID_ATTRIBUTE_NAME + '=' + + quoteAttributeValueForBrowser(id); }, /** @@ -2000,16 +2025,14 @@ var DOMPropertyOperations = { var attributeName = DOMProperty.getAttributeName[name]; if (DOMProperty.hasBooleanValue[name] || (DOMProperty.hasOverloadedBooleanValue[name] && value === true)) { - return escapeTextForBrowser(attributeName); + return attributeName; } - return processAttributeNameAndPrefix(attributeName) + - escapeTextForBrowser(value) + '"'; + return attributeName + '=' + quoteAttributeValueForBrowser(value); } else if (DOMProperty.isCustomAttribute(name)) { if (value == null) { return ''; } - return processAttributeNameAndPrefix(name) + - escapeTextForBrowser(value) + '"'; + return name + '=' + quoteAttributeValueForBrowser(value); } else if ("production" !== "development") { warnUnknownProperty(name); } @@ -2093,9 +2116,9 @@ var DOMPropertyOperations = { module.exports = DOMPropertyOperations; -},{"./DOMProperty":12,"./escapeTextForBrowser":123,"./memoizeStringOnly":149,"./warning":160}],14:[function(_dereq_,module,exports){ +},{"11":11,"163":163,"171":171}],13:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -2108,14 +2131,14 @@ module.exports = DOMPropertyOperations; /*jslint evil: true, sub: true */ -"use strict"; +'use strict'; -var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); +var ExecutionEnvironment = _dereq_(22); -var createNodesFromMarkup = _dereq_("./createNodesFromMarkup"); -var emptyFunction = _dereq_("./emptyFunction"); -var getMarkupWrap = _dereq_("./getMarkupWrap"); -var invariant = _dereq_("./invariant"); +var createNodesFromMarkup = _dereq_(126); +var emptyFunction = _dereq_(129); +var getMarkupWrap = _dereq_(142); +var invariant = _dereq_(150); var OPEN_TAG_NAME_EXP = /^(<[^ \/>]+)/; var RESULT_INDEX_ATTR = 'data-danger-index'; @@ -2178,7 +2201,8 @@ var Danger = { // This for-in loop skips the holes of the sparse array. The order of // iteration should follow the order of assignment, which happens to match // numerical index order, but we don't rely on that. - for (var resultIndex in markupListByNodeName) { + var resultIndex; + for (resultIndex in markupListByNodeName) { if (markupListByNodeName.hasOwnProperty(resultIndex)) { var markup = markupListByNodeName[resultIndex]; @@ -2199,8 +2223,8 @@ var Danger = { emptyFunction // Do nothing special with

; + * } + * }); * - * Components can also be "owned" by other components. Being owned by another - * component means being constructed by that component. This is different from - * being the child of a component, which means having a DOM representation that - * is a child of the DOM representation of that component. + * The class specification supports a specific protocol of methods that have + * special meaning (e.g. `render`). See `ReactClassInterface` for + * more the comprehensive protocol. Any other properties and methods in the + * class specification will available on the prototype. * - * @class ReactComponent + * @interface ReactClassInterface + * @internal */ -var ReactComponent = { +var ReactClassInterface = { - injection: { - injectEnvironment: function(ReactComponentEnvironment) { - ("production" !== "development" ? invariant( - !injected, - 'ReactComponent: injectEnvironment() can only be called once.' - ) : invariant(!injected)); - mountImageIntoNode = ReactComponentEnvironment.mountImageIntoNode; - unmountIDFromEnvironment = - ReactComponentEnvironment.unmountIDFromEnvironment; - ReactComponent.BackendIDOperations = - ReactComponentEnvironment.BackendIDOperations; - injected = true; - } - }, + /** + * An array of Mixin objects to include when defining your component. + * + * @type {array} + * @optional + */ + mixins: SpecPolicy.DEFINE_MANY, /** - * @internal + * An object containing properties and methods that should be defined on + * the component's constructor instead of its prototype (static methods). + * + * @type {object} + * @optional */ - LifeCycle: ComponentLifeCycle, + statics: SpecPolicy.DEFINE_MANY, /** - * Injected module that provides ability to mutate individual properties. - * Injected into the base class because many different subclasses need access - * to this. + * Definition of prop types for this component. * - * @internal + * @type {object} + * @optional */ - BackendIDOperations: null, + propTypes: SpecPolicy.DEFINE_MANY, /** - * Base functionality for every ReactComponent constructor. Mixed into the - * `ReactComponent` prototype, but exposed statically for easy access. + * Definition of context types for this component. * - * @lends {ReactComponent.prototype} + * @type {object} + * @optional */ - Mixin: { + contextTypes: SpecPolicy.DEFINE_MANY, - /** - * Checks whether or not this component is mounted. - * - * @return {boolean} True if mounted, false otherwise. - * @final - * @protected - */ - isMounted: function() { - return this._lifeCycleState === ComponentLifeCycle.MOUNTED; - }, + /** + * Definition of context types this component sets for its children. + * + * @type {object} + * @optional + */ + childContextTypes: SpecPolicy.DEFINE_MANY, - /** - * Sets a subset of the props. - * - * @param {object} partialProps Subset of the next props. - * @param {?function} callback Called after props are updated. - * @final - * @public - */ - setProps: function(partialProps, callback) { - // Merge with the pending element if it exists, otherwise with existing - // element props. - var element = this._pendingElement || this._currentElement; - this.replaceProps( - assign({}, element.props, partialProps), - callback - ); - }, + // ==== Definition methods ==== - /** - * Replaces all of the props. - * - * @param {object} props New props. - * @param {?function} callback Called after props are updated. - * @final - * @public - */ - replaceProps: function(props, callback) { - ("production" !== "development" ? invariant( - this.isMounted(), - 'replaceProps(...): Can only update a mounted component.' - ) : invariant(this.isMounted())); - ("production" !== "development" ? invariant( - this._mountDepth === 0, - 'replaceProps(...): You called `setProps` or `replaceProps` on a ' + - 'component with a parent. This is an anti-pattern since props will ' + - 'get reactively updated when rendered. Instead, change the owner\'s ' + - '`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 element. - // This creates an extra internal element. - this._pendingElement = ReactElement.cloneAndReplaceProps( - this._pendingElement || this._currentElement, - props - ); - ReactUpdates.enqueueUpdate(this, callback); - }, + /** + * Invoked when the component is mounted. Values in the mapping will be set on + * `this.props` if that prop is not specified (i.e. using an `in` check). + * + * This method is invoked before `getInitialState` and therefore cannot rely + * on `this.state` or use `this.setState`. + * + * @return {object} + * @optional + */ + getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED, - /** - * Schedule a partial update to the props. Only used for internal testing. - * - * @param {object} partialProps Subset of the next props. - * @param {?function} callback Called after props are updated. - * @final - * @internal - */ - _setPropsInternal: function(partialProps, callback) { - // 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); - }, + /** + * Invoked once before the component is mounted. The return value will be used + * as the initial value of `this.state`. + * + * getInitialState: function() { + * return { + * isOn: false, + * fooBaz: new BazFoo() + * } + * } + * + * @return {object} + * @optional + */ + getInitialState: SpecPolicy.DEFINE_MANY_MERGED, - /** - * Base constructor for all React components. - * - * Subclasses that override this method should make sure to invoke - * `ReactComponent.Mixin.construct.call(this, ...)`. - * - * @param {ReactElement} element - * @internal - */ - construct: function(element) { - // This is the public exposed props object after it has been processed - // with default props. The element's props represents the true internal - // state of the props. - this.props = element.props; - // Record the component responsible for creating this component. - // 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 = element._owner; - - // All components start unmounted. - this._lifeCycleState = ComponentLifeCycle.UNMOUNTED; - - // See ReactUpdates. - this._pendingCallbacks = null; - - // We keep the old element and a reference to the pending element - // to track updates. - this._currentElement = element; - this._pendingElement = null; - }, + /** + * @return {object} + * @optional + */ + getChildContext: SpecPolicy.DEFINE_MANY_MERGED, - /** - * Initializes the component, renders markup, and registers event listeners. - * - * NOTE: This does not insert any nodes into the DOM. - * - * Subclasses that override this method should make sure to invoke - * `ReactComponent.Mixin.mountComponent.call(this, ...)`. - * - * @param {string} rootID DOM ID of the root node. - * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction - * @param {number} mountDepth number of components in the owner hierarchy. - * @return {?string} Rendered markup to be inserted into the DOM. - * @internal - */ - mountComponent: function(rootID, transaction, mountDepth) { - ("production" !== "development" ? invariant( - !this.isMounted(), - 'mountComponent(%s, ...): Can only mount an unmounted component. ' + - 'Make sure to avoid storing components between renders or reusing a ' + - 'single component instance in multiple places.', - rootID - ) : invariant(!this.isMounted())); - 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; - this._mountDepth = mountDepth; - // Effectively: return ''; - }, - - /** - * Releases any resources allocated by `mountComponent`. - * - * NOTE: This does not remove any nodes from the DOM. - * - * Subclasses that override this method should make sure to invoke - * `ReactComponent.Mixin.unmountComponent.call(this)`. - * - * @internal - */ - unmountComponent: function() { - ("production" !== "development" ? invariant( - this.isMounted(), - 'unmountComponent(): Can only unmount a mounted component.' - ) : invariant(this.isMounted())); - var ref = this._currentElement.ref; - if (ref != null) { - ReactOwner.removeComponentAsRefFrom(this, ref, this._owner); - } - unmountIDFromEnvironment(this._rootNodeID); - this._rootNodeID = null; - this._lifeCycleState = ComponentLifeCycle.UNMOUNTED; - }, - - /** - * Given a new instance of this component, updates the rendered DOM nodes - * as if that instance was rendered instead. - * - * Subclasses that override this method should make sure to invoke - * `ReactComponent.Mixin.receiveComponent.call(this, ...)`. - * - * @param {object} nextComponent Next set of properties. - * @param {ReactReconcileTransaction} transaction - * @internal - */ - receiveComponent: function(nextElement, transaction) { - ("production" !== "development" ? invariant( - this.isMounted(), - 'receiveComponent(...): Can only update a mounted component.' - ) : invariant(this.isMounted())); - this._pendingElement = nextElement; - this.performUpdateIfNecessary(transaction); - }, - - /** - * If `_pendingElement` is set, update the component. - * - * @param {ReactReconcileTransaction} transaction - * @internal - */ - performUpdateIfNecessary: function(transaction) { - if (this._pendingElement == null) { - return; - } - 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} prevElement - * @internal - */ - 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 element instead - // of the public this.props because the post processing cannot determine - // 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 - // if you swap the keys of but not the refs. Reconsider where this check - // is made. It probably belongs where the key checking and - // instantiateReactComponent is done. - - if (nextElement._owner !== prevElement._owner || - nextElement.ref !== prevElement.ref) { - if (prevElement.ref != null) { - ReactOwner.removeComponentAsRefFrom( - this, prevElement.ref, prevElement._owner - ); - } - // Correct, even if the owner is the same, and only the ref has changed. - if (nextElement.ref != null) { - ReactOwner.addComponentAsRefTo( - this, - nextElement.ref, - nextElement._owner - ); - } - } - }, - - /** - * Mounts this component and inserts it into the DOM. - * - * @param {string} rootID DOM ID of the root node. - * @param {DOMElement} container DOM element to mount into. - * @param {boolean} shouldReuseMarkup If true, do not insert markup - * @final - * @internal - * @see {ReactMount.render} - */ - mountComponentIntoNode: function(rootID, container, shouldReuseMarkup) { - var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(); - transaction.perform( - this._mountComponentIntoNode, - this, - rootID, - container, - transaction, - shouldReuseMarkup - ); - ReactUpdates.ReactReconcileTransaction.release(transaction); - }, - - /** - * @param {string} rootID DOM ID of the root node. - * @param {DOMElement} container DOM element to mount into. - * @param {ReactReconcileTransaction} transaction - * @param {boolean} shouldReuseMarkup If true, do not insert markup - * @final - * @private - */ - _mountComponentIntoNode: function( - rootID, - container, - transaction, - shouldReuseMarkup) { - var markup = this.mountComponent(rootID, transaction, 0); - mountImageIntoNode(markup, container, shouldReuseMarkup); - }, - - /** - * Checks if this component is owned by the supplied `owner` component. - * - * @param {ReactComponent} owner Component to check. - * @return {boolean} True if `owners` owns this component. - * @final - * @internal - */ - isOwnedBy: function(owner) { - return this._owner === owner; - }, - - /** - * Gets another component, that shares the same owner as this one, by ref. - * - * @param {string} ref of a sibling Component. - * @return {?ReactComponent} the actual sibling Component. - * @final - * @internal - */ - getSiblingByRef: function(ref) { - var owner = this._owner; - if (!owner || !owner.refs) { - return null; - } - return owner.refs[ref]; - } - } -}; - -module.exports = ReactComponent; - -},{"./Object.assign":29,"./ReactElement":58,"./ReactOwner":74,"./ReactUpdates":91,"./invariant":140,"./keyMirror":146}],38:[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 ReactComponentBrowserEnvironment - */ - -/*jslint evil: true */ + /** + * Uses props from `this.props` and state from `this.state` to render the + * structure of the component. + * + * No guarantees are made about when or how often this method is invoked, so + * it must not have side effects. + * + * render: function() { + * var name = this.props.name; + * return
Hello, {name}!
; + * } + * + * @return {ReactComponent} + * @nosideeffects + * @required + */ + render: SpecPolicy.DEFINE_ONCE, -"use strict"; -var ReactDOMIDOperations = _dereq_("./ReactDOMIDOperations"); -var ReactMarkupChecksum = _dereq_("./ReactMarkupChecksum"); -var ReactMount = _dereq_("./ReactMount"); -var ReactPerf = _dereq_("./ReactPerf"); -var ReactReconcileTransaction = _dereq_("./ReactReconcileTransaction"); -var getReactRootElementInContainer = _dereq_("./getReactRootElementInContainer"); -var invariant = _dereq_("./invariant"); -var setInnerHTML = _dereq_("./setInnerHTML"); + // ==== Delegate methods ==== + /** + * Invoked when the component is initially created and about to be mounted. + * This may have side effects, but any external subscriptions or data created + * by this method must be cleaned up in `componentWillUnmount`. + * + * @optional + */ + componentWillMount: SpecPolicy.DEFINE_MANY, -var ELEMENT_NODE_TYPE = 1; -var DOC_NODE_TYPE = 9; + /** + * Invoked when the component has been mounted and has a DOM representation. + * However, there is no guarantee that the DOM node is in the document. + * + * Use this as an opportunity to operate on the DOM when the component has + * been mounted (initialized and rendered) for the first time. + * + * @param {DOMElement} rootNode DOM element representing the component. + * @optional + */ + componentDidMount: SpecPolicy.DEFINE_MANY, + /** + * Invoked before the component receives new props. + * + * Use this as an opportunity to react to a prop transition by updating the + * state using `this.setState`. Current props are accessed via `this.props`. + * + * componentWillReceiveProps: function(nextProps, nextContext) { + * this.setState({ + * likesIncreasing: nextProps.likeCount > this.props.likeCount + * }); + * } + * + * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop + * transition may cause a state change, but the opposite is not true. If you + * need it, you are probably looking for `componentWillUpdate`. + * + * @param {object} nextProps + * @optional + */ + componentWillReceiveProps: SpecPolicy.DEFINE_MANY, -/** - * Abstracts away all functionality of `ReactComponent` requires knowledge of - * the browser context. - */ -var ReactComponentBrowserEnvironment = { - ReactReconcileTransaction: ReactReconcileTransaction, + /** + * Invoked while deciding if the component should be updated as a result of + * receiving new props, state and/or context. + * + * Use this as an opportunity to `return false` when you're certain that the + * transition to the new props/state/context will not require a component + * update. + * + * shouldComponentUpdate: function(nextProps, nextState, nextContext) { + * return !equal(nextProps, this.props) || + * !equal(nextState, this.state) || + * !equal(nextContext, this.context); + * } + * + * @param {object} nextProps + * @param {?object} nextState + * @param {?object} nextContext + * @return {boolean} True if the component should update. + * @optional + */ + shouldComponentUpdate: SpecPolicy.DEFINE_ONCE, - BackendIDOperations: ReactDOMIDOperations, + /** + * Invoked when the component is about to update due to a transition from + * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState` + * and `nextContext`. + * + * Use this as an opportunity to perform preparation before an update occurs. + * + * NOTE: You **cannot** use `this.setState()` in this method. + * + * @param {object} nextProps + * @param {?object} nextState + * @param {?object} nextContext + * @param {ReactReconcileTransaction} transaction + * @optional + */ + componentWillUpdate: SpecPolicy.DEFINE_MANY, /** - * If a particular environment requires that some resources be cleaned up, - * specify this in the injected Mixin. In the DOM, we would likely want to - * purge any cached node ID lookups. + * Invoked when the component's DOM representation has been updated. * - * @private + * Use this as an opportunity to operate on the DOM when the component has + * been updated. + * + * @param {object} prevProps + * @param {?object} prevState + * @param {?object} prevContext + * @param {DOMElement} rootNode DOM element representing the component. + * @optional */ - unmountIDFromEnvironment: function(rootNodeID) { - ReactMount.purgeID(rootNodeID); - }, + componentDidUpdate: SpecPolicy.DEFINE_MANY, /** - * @param {string} markup Markup string to place into the DOM Element. - * @param {DOMElement} container DOM Element to insert markup into. - * @param {boolean} shouldReuseMarkup Should reuse the existing markup in the - * container if possible. + * Invoked when the component is about to be removed from its parent and have + * its DOM representation destroyed. + * + * Use this as an opportunity to deallocate any external resources. + * + * NOTE: There is no `componentDidUnmount` since your component will have been + * destroyed by that point. + * + * @optional */ - mountImageIntoNode: ReactPerf.measure( - 'ReactComponentBrowserEnvironment', - 'mountImageIntoNode', - function(markup, container, shouldReuseMarkup) { - ("production" !== "development" ? invariant( - container && ( - container.nodeType === ELEMENT_NODE_TYPE || - container.nodeType === DOC_NODE_TYPE - ), - 'mountComponentIntoNode(...): Target container is not valid.' - ) : invariant(container && ( - container.nodeType === ELEMENT_NODE_TYPE || - container.nodeType === DOC_NODE_TYPE - ))); + componentWillUnmount: SpecPolicy.DEFINE_MANY, - if (shouldReuseMarkup) { - if (ReactMarkupChecksum.canReuseMarkup( - markup, - getReactRootElementInContainer(container))) { - return; - } else { - ("production" !== "development" ? invariant( - container.nodeType !== DOC_NODE_TYPE, - 'You\'re trying to render a component to the document using ' + - 'server rendering but the checksum was invalid. This usually ' + - 'means you rendered a different component type or props on ' + - 'the client from the one on the server, or your render() ' + - 'methods are impure. React cannot handle this case due to ' + - 'cross-browser quirks by rendering at the document root. You ' + - 'should look for environment dependent code in your components ' + - 'and ensure the props are the same client and server side.' - ) : invariant(container.nodeType !== DOC_NODE_TYPE)); - if ("production" !== "development") { - console.warn( - 'React attempted to use reuse markup in a container but the ' + - 'checksum was invalid. This generally means that you are ' + - 'using server rendering and the markup generated on the ' + - 'server was not what the client was expecting. React injected ' + - 'new markup to compensate which works but you have lost many ' + - 'of the benefits of server rendering. Instead, figure out ' + - 'why the markup being generated is different on the client ' + - 'or server.' - ); - } - } - } - ("production" !== "development" ? invariant( - container.nodeType !== DOC_NODE_TYPE, - 'You\'re trying to render a component to the document but ' + - 'you didn\'t use server rendering. We can\'t do this ' + - 'without using server rendering due to cross-browser quirks. ' + - 'See renderComponentToString() for server rendering.' - ) : invariant(container.nodeType !== DOC_NODE_TYPE)); + // ==== Advanced methods ==== - setInnerHTML(container, markup); - } - ) -}; + /** + * Updates the component's currently mounted DOM representation. + * + * By default, this implements React's rendering and reconciliation algorithm. + * Sophisticated clients may wish to override this. + * + * @param {ReactReconcileTransaction} transaction + * @internal + * @overridable + */ + updateComponent: SpecPolicy.OVERRIDE_BASE -module.exports = ReactComponentBrowserEnvironment; +}; -},{"./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. - * 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. + * Mapping from class specification keys to special processing functions. * -* @providesModule ReactComponentWithPureRenderMixin -*/ - -"use strict"; - -var shallowEqual = _dereq_("./shallowEqual"); - -/** - * If your React component's render function is "pure", e.g. it will render the - * same result given the same props and state, provide this Mixin for a - * considerable performance boost. - * - * Most React components have pure render functions. - * - * Example: - * - * var ReactComponentWithPureRenderMixin = - * require('ReactComponentWithPureRenderMixin'); - * React.createClass({ - * mixins: [ReactComponentWithPureRenderMixin], - * - * render: function() { - * return
foo
; - * } - * }); - * - * Note: This only checks shallow equality for props and state. If these contain - * complex data structures this mixin may have false-negatives for deeper - * differences. Only mixin to components which have simple props and state, or - * use `forceUpdate()` when you know deep data structures have changed. + * Although these are declared like instance properties in the specification + * when defining classes using `React.createClass`, they are actually static + * and are accessible on the constructor instead of the prototype. Despite + * being static, they must be defined outside of the "statics" key under + * which all other static methods are defined. */ -var ReactComponentWithPureRenderMixin = { - shouldComponentUpdate: function(nextProps, nextState) { - return !shallowEqual(this.props, nextProps) || - !shallowEqual(this.state, nextState); +var RESERVED_SPEC_KEYS = { + displayName: function(Constructor, displayName) { + Constructor.displayName = displayName; + }, + mixins: function(Constructor, mixins) { + if (mixins) { + for (var i = 0; i < mixins.length; i++) { + mixSpecIntoComponent(Constructor, mixins[i]); + } + } + }, + childContextTypes: function(Constructor, childContextTypes) { + if ("production" !== "development") { + validateTypeDef( + Constructor, + childContextTypes, + ReactPropTypeLocations.childContext + ); + } + Constructor.childContextTypes = assign( + {}, + Constructor.childContextTypes, + childContextTypes + ); + }, + contextTypes: function(Constructor, contextTypes) { + if ("production" !== "development") { + validateTypeDef( + Constructor, + contextTypes, + ReactPropTypeLocations.context + ); + } + Constructor.contextTypes = assign( + {}, + Constructor.contextTypes, + contextTypes + ); + }, + /** + * Special case getDefaultProps which should move into statics but requires + * automatic merging. + */ + getDefaultProps: function(Constructor, getDefaultProps) { + if (Constructor.getDefaultProps) { + Constructor.getDefaultProps = createMergedResultFunction( + Constructor.getDefaultProps, + getDefaultProps + ); + } else { + Constructor.getDefaultProps = getDefaultProps; + } + }, + propTypes: function(Constructor, propTypes) { + if ("production" !== "development") { + validateTypeDef( + Constructor, + propTypes, + ReactPropTypeLocations.prop + ); + } + Constructor.propTypes = assign( + {}, + Constructor.propTypes, + propTypes + ); + }, + statics: function(Constructor, statics) { + mixStaticSpecIntoComponent(Constructor, statics); } }; -module.exports = ReactComponentWithPureRenderMixin; - -},{"./shallowEqual":155}],40:[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 ReactCompositeComponent - */ +function validateTypeDef(Constructor, typeDef, location) { + for (var propName in typeDef) { + if (typeDef.hasOwnProperty(propName)) { + // use a warning instead of an invariant so components + // don't show up in prod but not in __DEV__ + ("production" !== "development" ? warning( + typeof typeDef[propName] === 'function', + '%s: %s type `%s` is invalid; it must be a function, usually from ' + + 'React.PropTypes.', + Constructor.displayName || 'ReactClass', + ReactPropTypeLocationNames[location], + propName + ) : null); + } + } +} -"use strict"; +function validateMethodOverride(proto, name) { + var specPolicy = ReactClassInterface.hasOwnProperty(name) ? + ReactClassInterface[name] : + null; -var ReactComponent = _dereq_("./ReactComponent"); -var ReactContext = _dereq_("./ReactContext"); -var ReactCurrentOwner = _dereq_("./ReactCurrentOwner"); -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"); -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 keyOf = _dereq_("./keyOf"); -var monitorCodeUse = _dereq_("./monitorCodeUse"); -var mapObject = _dereq_("./mapObject"); -var shouldUpdateReactComponent = _dereq_("./shouldUpdateReactComponent"); -var warning = _dereq_("./warning"); + // Disallow overriding of base class methods unless explicitly allowed. + if (ReactClassMixin.hasOwnProperty(name)) { + ("production" !== "development" ? invariant( + specPolicy === SpecPolicy.OVERRIDE_BASE, + 'ReactClassInterface: You are attempting to override ' + + '`%s` from your class specification. Ensure that your method names ' + + 'do not overlap with React methods.', + name + ) : invariant(specPolicy === SpecPolicy.OVERRIDE_BASE)); + } -var MIXINS_KEY = keyOf({mixins: null}); + // Disallow defining methods more than once unless explicitly allowed. + if (proto.hasOwnProperty(name)) { + ("production" !== "development" ? invariant( + specPolicy === SpecPolicy.DEFINE_MANY || + specPolicy === SpecPolicy.DEFINE_MANY_MERGED, + 'ReactClassInterface: You are attempting to define ' + + '`%s` on your component more than once. This conflict may be due ' + + 'to a mixin.', + name + ) : invariant(specPolicy === SpecPolicy.DEFINE_MANY || + specPolicy === SpecPolicy.DEFINE_MANY_MERGED)); + } +} /** - * Policies that describe methods in `ReactCompositeComponentInterface`. + * Mixin helper which handles policy validation and reserved + * specification keys when building React classses. */ -var SpecPolicy = keyMirror({ - /** - * These methods may be defined only once by the class specification or mixin. - */ - DEFINE_ONCE: null, - /** - * These methods may be defined by both the class specification and mixins. - * Subsequent definitions will be chained. These methods must return void. - */ - DEFINE_MANY: null, - /** - * These methods are overriding the base ReactCompositeComponent class. - */ - OVERRIDE_BASE: null, - /** - * These methods are similar to DEFINE_MANY, except we assume they return - * objects. We try to merge the keys of the return values of all the mixed in - * functions. If there is a key conflict we throw. - */ - DEFINE_MANY_MERGED: null -}); +function mixSpecIntoComponent(Constructor, spec) { + if (!spec) { + return; + } + ("production" !== "development" ? invariant( + typeof spec !== 'function', + 'ReactClass: You\'re attempting to ' + + 'use a component class as a mixin. Instead, just use a regular object.' + ) : invariant(typeof spec !== 'function')); + ("production" !== "development" ? invariant( + !ReactElement.isValidElement(spec), + 'ReactClass: You\'re attempting to ' + + 'use a component as a mixin. Instead, just use a regular object.' + ) : invariant(!ReactElement.isValidElement(spec))); -var injectedMixins = []; + var proto = Constructor.prototype; -/** - * Composite components are higher-level components that compose other composite - * or native components. - * - * To create a new type of `ReactCompositeComponent`, pass a specification of - * your new class to `React.createClass`. The only requirement of your class - * specification is that you implement a `render` method. - * - * var MyComponent = React.createClass({ - * render: function() { - * return
Hello World
; - * } - * }); - * - * The class specification supports a specific protocol of methods that have - * special meaning (e.g. `render`). See `ReactCompositeComponentInterface` for - * more the comprehensive protocol. Any other properties and methods in the - * class specification will available on the prototype. - * - * @interface ReactCompositeComponentInterface - * @internal - */ -var ReactCompositeComponentInterface = { + // 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); + } - /** - * An array of Mixin objects to include when defining your component. - * - * @type {array} - * @optional - */ - mixins: SpecPolicy.DEFINE_MANY, + for (var name in spec) { + if (!spec.hasOwnProperty(name)) { + continue; + } - /** - * An object containing properties and methods that should be defined on - * the component's constructor instead of its prototype (static methods). - * - * @type {object} - * @optional - */ - statics: SpecPolicy.DEFINE_MANY, + if (name === MIXINS_KEY) { + // We have already handled mixins in a special case above + continue; + } - /** - * Definition of prop types for this component. - * - * @type {object} - * @optional - */ - propTypes: SpecPolicy.DEFINE_MANY, + var property = spec[name]; + validateMethodOverride(proto, name); - /** - * Definition of context types for this component. - * - * @type {object} - * @optional - */ - contextTypes: SpecPolicy.DEFINE_MANY, + if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) { + RESERVED_SPEC_KEYS[name](Constructor, property); + } else { + // Setup methods on prototype: + // The following member methods should not be automatically bound: + // 1. Expected ReactClass methods (in the "interface"). + // 2. Overridden methods (that were mixed in). + var isReactClassMethod = + ReactClassInterface.hasOwnProperty(name); + var isAlreadyDefined = proto.hasOwnProperty(name); + var markedDontBind = property && property.__reactDontBind; + var isFunction = typeof property === 'function'; + var shouldAutoBind = + isFunction && + !isReactClassMethod && + !isAlreadyDefined && + !markedDontBind; - /** - * Definition of context types this component sets for its children. - * - * @type {object} - * @optional - */ - childContextTypes: SpecPolicy.DEFINE_MANY, + if (shouldAutoBind) { + if (!proto.__reactAutoBindMap) { + proto.__reactAutoBindMap = {}; + } + proto.__reactAutoBindMap[name] = property; + proto[name] = property; + } else { + if (isAlreadyDefined) { + var specPolicy = ReactClassInterface[name]; - // ==== Definition methods ==== + // These cases should already be caught by validateMethodOverride + ("production" !== "development" ? invariant( + isReactClassMethod && ( + (specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY) + ), + 'ReactClass: Unexpected spec policy %s for key %s ' + + 'when mixing in component specs.', + specPolicy, + name + ) : invariant(isReactClassMethod && ( + (specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY) + ))); - /** - * Invoked when the component is mounted. Values in the mapping will be set on - * `this.props` if that prop is not specified (i.e. using an `in` check). - * - * This method is invoked before `getInitialState` and therefore cannot rely - * on `this.state` or use `this.setState`. - * - * @return {object} - * @optional - */ - getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED, + // For methods which are defined more than once, call the existing + // methods before calling the new property, merging if appropriate. + if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) { + proto[name] = createMergedResultFunction(proto[name], property); + } else if (specPolicy === SpecPolicy.DEFINE_MANY) { + proto[name] = createChainedFunction(proto[name], property); + } + } else { + proto[name] = property; + if ("production" !== "development") { + // Add verbose displayName to the function, which helps when looking + // at profiling tools. + if (typeof property === 'function' && spec.displayName) { + proto[name].displayName = spec.displayName + '_' + name; + } + } + } + } + } + } +} - /** - * Invoked once before the component is mounted. The return value will be used - * as the initial value of `this.state`. - * - * getInitialState: function() { - * return { - * isOn: false, - * fooBaz: new BazFoo() - * } - * } - * - * @return {object} - * @optional - */ - getInitialState: SpecPolicy.DEFINE_MANY_MERGED, +function mixStaticSpecIntoComponent(Constructor, statics) { + if (!statics) { + return; + } + for (var name in statics) { + var property = statics[name]; + if (!statics.hasOwnProperty(name)) { + continue; + } - /** - * @return {object} - * @optional - */ - getChildContext: SpecPolicy.DEFINE_MANY_MERGED, + var isReserved = name in RESERVED_SPEC_KEYS; + ("production" !== "development" ? invariant( + !isReserved, + 'ReactClass: 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)); - /** - * Uses props from `this.props` and state from `this.state` to render the - * structure of the component. - * - * No guarantees are made about when or how often this method is invoked, so - * it must not have side effects. - * - * render: function() { - * var name = this.props.name; - * return
Hello, {name}!
; - * } - * - * @return {ReactComponent} - * @nosideeffects - * @required - */ - render: SpecPolicy.DEFINE_ONCE, + var isInherited = name in Constructor; + ("production" !== "development" ? invariant( + !isInherited, + 'ReactClass: 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; + } +} + +/** + * Merge two objects, but throw if both contain the same key. + * + * @param {object} one The first object, which is mutated. + * @param {object} two The second object + * @return {object} one after it has been mutated to contain everything in two. + */ +function mergeIntoWithNoDuplicateKeys(one, two) { + ("production" !== "development" ? invariant( + one && two && typeof one === 'object' && typeof two === 'object', + 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.' + ) : invariant(one && two && typeof one === 'object' && typeof two === 'object')); + + for (var key in two) { + if (two.hasOwnProperty(key)) { + ("production" !== "development" ? invariant( + one[key] === undefined, + 'mergeIntoWithNoDuplicateKeys(): ' + + '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] = two[key]; + } + } + return one; +} +/** + * Creates a function that invokes two functions and merges their return values. + * + * @param {function} one Function to invoke first. + * @param {function} two Function to invoke second. + * @return {function} Function that invokes the two argument functions. + * @private + */ +function createMergedResultFunction(one, two) { + return function mergedResult() { + var a = one.apply(this, arguments); + var b = two.apply(this, arguments); + if (a == null) { + return b; + } else if (b == null) { + return a; + } + var c = {}; + mergeIntoWithNoDuplicateKeys(c, a); + mergeIntoWithNoDuplicateKeys(c, b); + return c; + }; +} +/** + * Creates a function that invokes two functions and ignores their return vales. + * + * @param {function} one Function to invoke first. + * @param {function} two Function to invoke second. + * @return {function} Function that invokes the two argument functions. + * @private + */ +function createChainedFunction(one, two) { + return function chainedFunction() { + one.apply(this, arguments); + two.apply(this, arguments); + }; +} - // ==== Delegate methods ==== +/** + * Binds a method to the component. + * + * @param {object} component Component whose method is going to be bound. + * @param {function} method Method to be bound. + * @return {function} The bound method. + */ +function bindAutoBindMethod(component, method) { + 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; + /* eslint-disable block-scoped-var, no-undef */ + 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. + if (newThis !== component && newThis !== null) { + ("production" !== "development" ? warning( + false, + 'bind(): React component methods may only be bound to the ' + + 'component instance. See %s', + componentName + ) : null); + } else if (!args.length) { + ("production" !== "development" ? warning( + false, + 'bind(): You are binding a component method to the component. ' + + 'React does this for you automatically in a high-performance ' + + 'way, so you can safely remove this call. See %s', + componentName + ) : null); + return boundMethod; + } + var reboundMethod = _bind.apply(boundMethod, arguments); + reboundMethod.__reactBoundContext = component; + reboundMethod.__reactBoundMethod = method; + reboundMethod.__reactBoundArguments = args; + return reboundMethod; + /* eslint-enable */ + }; + } + return boundMethod; +} - /** - * Invoked when the component is initially created and about to be mounted. - * This may have side effects, but any external subscriptions or data created - * by this method must be cleaned up in `componentWillUnmount`. - * - * @optional - */ - componentWillMount: SpecPolicy.DEFINE_MANY, +/** + * Binds all auto-bound methods in a component. + * + * @param {object} component Component whose method is going to be bound. + */ +function bindAutoBindMethods(component) { + for (var autoBindKey in component.__reactAutoBindMap) { + if (component.__reactAutoBindMap.hasOwnProperty(autoBindKey)) { + var method = component.__reactAutoBindMap[autoBindKey]; + component[autoBindKey] = bindAutoBindMethod( + component, + ReactErrorUtils.guard( + method, + component.constructor.displayName + '.' + autoBindKey + ) + ); + } + } +} - /** - * Invoked when the component has been mounted and has a DOM representation. - * However, there is no guarantee that the DOM node is in the document. - * - * Use this as an opportunity to operate on the DOM when the component has - * been mounted (initialized and rendered) for the first time. - * - * @param {DOMElement} rootNode DOM element representing the component. - * @optional - */ - componentDidMount: SpecPolicy.DEFINE_MANY, +var typeDeprecationDescriptor = { + enumerable: false, + get: function() { + var displayName = this.displayName || this.name || 'Component'; + ("production" !== "development" ? warning( + false, + '%s.type is deprecated. Use %s directly to access the class.', + displayName, + displayName + ) : null); + Object.defineProperty(this, 'type', { + value: this + }); + return this; + } +}; - /** - * Invoked before the component receives new props. - * - * Use this as an opportunity to react to a prop transition by updating the - * state using `this.setState`. Current props are accessed via `this.props`. - * - * componentWillReceiveProps: function(nextProps, nextContext) { - * this.setState({ - * likesIncreasing: nextProps.likeCount > this.props.likeCount - * }); - * } - * - * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop - * transition may cause a state change, but the opposite is not true. If you - * need it, you are probably looking for `componentWillUpdate`. - * - * @param {object} nextProps - * @optional - */ - componentWillReceiveProps: SpecPolicy.DEFINE_MANY, +/** + * Add more to the ReactClass base class. These are all legacy features and + * therefore not already part of the modern ReactComponent. + */ +var ReactClassMixin = { - /** - * Invoked while deciding if the component should be updated as a result of - * receiving new props, state and/or context. - * - * Use this as an opportunity to `return false` when you're certain that the - * transition to the new props/state/context will not require a component - * update. - * - * shouldComponentUpdate: function(nextProps, nextState, nextContext) { - * return !equal(nextProps, this.props) || - * !equal(nextState, this.state) || - * !equal(nextContext, this.context); - * } - * - * @param {object} nextProps - * @param {?object} nextState - * @param {?object} nextContext - * @return {boolean} True if the component should update. - * @optional + /** + * TODO: This will be deprecated because state should always keep a consistent + * type signature and the only use case for this, is to avoid that. */ - shouldComponentUpdate: SpecPolicy.DEFINE_ONCE, + replaceState: function(newState, callback) { + ReactUpdateQueue.enqueueReplaceState(this, newState); + if (callback) { + ReactUpdateQueue.enqueueCallback(this, callback); + } + }, /** - * Invoked when the component is about to update due to a transition from - * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState` - * and `nextContext`. - * - * Use this as an opportunity to perform preparation before an update occurs. - * - * NOTE: You **cannot** use `this.setState()` in this method. - * - * @param {object} nextProps - * @param {?object} nextState - * @param {?object} nextContext - * @param {ReactReconcileTransaction} transaction - * @optional + * Checks whether or not this composite component is mounted. + * @return {boolean} True if mounted, false otherwise. + * @protected + * @final */ - componentWillUpdate: SpecPolicy.DEFINE_MANY, + isMounted: function() { + if ("production" !== "development") { + var owner = ReactCurrentOwner.current; + if (owner !== null) { + ("production" !== "development" ? warning( + owner._warnedAboutRefsInRender, + '%s is accessing isMounted inside its render() function. ' + + 'render() should be a pure function of props and state. It should ' + + 'never access something that requires stale data from the previous ' + + 'render, such as refs. Move this logic to componentDidMount and ' + + 'componentDidUpdate instead.', + owner.getName() || 'A component' + ) : null); + owner._warnedAboutRefsInRender = true; + } + } + var internalInstance = ReactInstanceMap.get(this); + return ( + internalInstance && + internalInstance !== ReactLifeCycle.currentlyMountingInstance + ); + }, /** - * Invoked when the component's DOM representation has been updated. + * Sets a subset of the props. * - * Use this as an opportunity to operate on the DOM when the component has - * been updated. - * - * @param {object} prevProps - * @param {?object} prevState - * @param {?object} prevContext - * @param {DOMElement} rootNode DOM element representing the component. - * @optional + * @param {object} partialProps Subset of the next props. + * @param {?function} callback Called after props are updated. + * @final + * @public + * @deprecated */ - componentDidUpdate: SpecPolicy.DEFINE_MANY, + setProps: function(partialProps, callback) { + ReactUpdateQueue.enqueueSetProps(this, partialProps); + if (callback) { + ReactUpdateQueue.enqueueCallback(this, callback); + } + }, /** - * Invoked when the component is about to be removed from its parent and have - * its DOM representation destroyed. - * - * Use this as an opportunity to deallocate any external resources. - * - * NOTE: There is no `componentDidUnmount` since your component will have been - * destroyed by that point. + * Replace all the props. * - * @optional + * @param {object} newProps Subset of the next props. + * @param {?function} callback Called after props are updated. + * @final + * @public + * @deprecated */ - componentWillUnmount: SpecPolicy.DEFINE_MANY, - + replaceProps: function(newProps, callback) { + ReactUpdateQueue.enqueueReplaceProps(this, newProps); + if (callback) { + ReactUpdateQueue.enqueueCallback(this, callback); + } + } +}; +var ReactClassComponent = function() {}; +assign( + ReactClassComponent.prototype, + ReactComponent.prototype, + ReactClassMixin +); - // ==== Advanced methods ==== +/** + * Module for creating composite components. + * + * @class ReactClass + */ +var ReactClass = { /** - * Updates the component's currently mounted DOM representation. - * - * By default, this implements React's rendering and reconciliation algorithm. - * Sophisticated clients may wish to override this. + * Creates a composite component class given a class specification. * - * @param {ReactReconcileTransaction} transaction - * @internal - * @overridable + * @param {object} spec Class specification (which must define `render`). + * @return {function} Component constructor function. + * @public */ - updateComponent: SpecPolicy.OVERRIDE_BASE + createClass: function(spec) { + var Constructor = function(props, context) { + // This constructor is overridden by mocks. The argument is used + // by mocks to assert on what gets mounted. -}; + if ("production" !== "development") { + ("production" !== "development" ? warning( + this instanceof Constructor, + 'Something is calling a React component directly. Use a factory or ' + + 'JSX instead. See: http://fb.me/react-legacyfactory' + ) : null); + } -/** - * Mapping from class specification keys to special processing functions. - * - * Although these are declared like instance properties in the specification - * when defining classes using `React.createClass`, they are actually static - * and are accessible on the constructor instead of the prototype. Despite - * being static, they must be defined outside of the "statics" key under - * which all other static methods are defined. - */ -var RESERVED_SPEC_KEYS = { - displayName: function(Constructor, displayName) { - Constructor.displayName = displayName; - }, - mixins: function(Constructor, mixins) { - if (mixins) { - for (var i = 0; i < mixins.length; i++) { - mixSpecIntoComponent(Constructor, mixins[i]); + // Wire up auto-binding + if (this.__reactAutoBindMap) { + bindAutoBindMethods(this); } - } - }, - childContextTypes: function(Constructor, childContextTypes) { - validateTypeDef( - Constructor, - childContextTypes, - ReactPropTypeLocations.childContext - ); - Constructor.childContextTypes = assign( - {}, - Constructor.childContextTypes, - childContextTypes - ); - }, - contextTypes: function(Constructor, contextTypes) { - validateTypeDef( - Constructor, - contextTypes, - ReactPropTypeLocations.context - ); - Constructor.contextTypes = assign( - {}, - Constructor.contextTypes, - contextTypes + + this.props = props; + this.context = context; + this.state = null; + + // ReactClasses doesn't have constructors. Instead, they use the + // getInitialState and componentWillMount methods for initialization. + + var initialState = this.getInitialState ? this.getInitialState() : null; + if ("production" !== "development") { + // We allow auto-mocks to proceed as if they're returning null. + if (typeof initialState === 'undefined' && + this.getInitialState._isMockFunction) { + // This is probably bad practice. Consider warning here and + // deprecating this convenience. + initialState = null; + } + } + ("production" !== "development" ? invariant( + typeof initialState === 'object' && !Array.isArray(initialState), + '%s.getInitialState(): must return an object or null', + Constructor.displayName || 'ReactCompositeComponent' + ) : invariant(typeof initialState === 'object' && !Array.isArray(initialState))); + + this.state = initialState; + }; + Constructor.prototype = new ReactClassComponent(); + Constructor.prototype.constructor = Constructor; + + injectedMixins.forEach( + mixSpecIntoComponent.bind(null, Constructor) ); - }, - /** - * Special case getDefaultProps which should move into statics but requires - * automatic merging. - */ - getDefaultProps: function(Constructor, getDefaultProps) { + + mixSpecIntoComponent(Constructor, spec); + + // Initialize the defaultProps property after all mixins have been merged if (Constructor.getDefaultProps) { - Constructor.getDefaultProps = createMergedResultFunction( - Constructor.getDefaultProps, - getDefaultProps - ); - } else { - Constructor.getDefaultProps = getDefaultProps; + Constructor.defaultProps = Constructor.getDefaultProps(); } + + if ("production" !== "development") { + // This is a tag to indicate that the use of these method names is ok, + // since it's used with createClass. If it's not, then it's likely a + // mistake so we'll warn you to use the static property, property + // initializer or constructor respectively. + if (Constructor.getDefaultProps) { + Constructor.getDefaultProps.isReactClassApproved = {}; + } + if (Constructor.prototype.getInitialState) { + Constructor.prototype.getInitialState.isReactClassApproved = {}; + } + } + + ("production" !== "development" ? invariant( + Constructor.prototype.render, + 'createClass(...): Class specification must implement a `render` method.' + ) : invariant(Constructor.prototype.render)); + + if ("production" !== "development") { + ("production" !== "development" ? warning( + !Constructor.prototype.componentShouldUpdate, + '%s has a method called ' + + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + + 'The name is phrased as a question because the function is ' + + 'expected to return a value.', + spec.displayName || 'A component' + ) : null); + } + + // Reduce time spent doing lookups by setting these on the prototype. + for (var methodName in ReactClassInterface) { + if (!Constructor.prototype[methodName]) { + Constructor.prototype[methodName] = null; + } + } + + // Legacy hook + Constructor.type = Constructor; + if ("production" !== "development") { + try { + Object.defineProperty(Constructor, 'type', typeDeprecationDescriptor); + } catch (x) { + // IE will fail on defineProperty (es5-shim/sham too) + } + } + + return Constructor; }, - propTypes: function(Constructor, propTypes) { - validateTypeDef( - Constructor, - propTypes, - ReactPropTypeLocations.prop - ); - Constructor.propTypes = assign( - {}, - Constructor.propTypes, - propTypes - ); - }, - statics: function(Constructor, statics) { - mixStaticSpecIntoComponent(Constructor, statics); + + injection: { + injectMixin: function(mixin) { + injectedMixins.push(mixin); + } } + }; -function getDeclarationErrorAddendum(component) { - var owner = component._owner || null; - if (owner && owner.constructor && owner.constructor.displayName) { - return ' Check the render method of `' + owner.constructor.displayName + - '`.'; - } - return ''; +module.exports = ReactClass; + +},{"150":150,"156":156,"157":157,"171":171,"29":29,"39":39,"45":45,"63":63,"66":66,"73":73,"74":74,"84":84,"85":85,"99":99}],39:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, 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 ReactComponent + */ + +'use strict'; + +var ReactUpdateQueue = _dereq_(99); + +var invariant = _dereq_(150); +var warning = _dereq_(171); + +/** + * Base class helpers for the updating state of a component. + */ +function ReactComponent(props, context) { + this.props = props; + this.context = context; } -function validateTypeDef(Constructor, typeDef, location) { - for (var propName in typeDef) { - if (typeDef.hasOwnProperty(propName)) { - ("production" !== "development" ? invariant( - typeof typeDef[propName] == 'function', - '%s: %s type `%s` is invalid; it must be a function, usually from ' + - 'React.PropTypes.', - Constructor.displayName || 'ReactCompositeComponent', - ReactPropTypeLocationNames[location], - propName - ) : invariant(typeof typeDef[propName] == 'function')); +/** + * Sets a subset of the state. Always use this to mutate + * state. You should treat `this.state` as immutable. + * + * There is no guarantee that `this.state` will be immediately updated, so + * accessing `this.state` after calling this method may return the old value. + * + * There is no guarantee that calls to `setState` will run synchronously, + * as they may eventually be batched together. You can provide an optional + * callback that will be executed when the call to setState is actually + * completed. + * + * When a function is provided to setState, it will be called at some point in + * the future (not synchronously). It will be called with the up to date + * component arguments (state, props, context). These values can be different + * from this.* because your function may be called after receiveProps but before + * shouldComponentUpdate, and this new state, props, and context will not yet be + * assigned to this. + * + * @param {object|function} partialState Next partial state or function to + * produce next partial state to be merged with current state. + * @param {?function} callback Called after state is updated. + * @final + * @protected + */ +ReactComponent.prototype.setState = function(partialState, callback) { + ("production" !== "development" ? invariant( + typeof partialState === 'object' || + typeof partialState === 'function' || + partialState == null, + 'setState(...): takes an object of state variables to update or a ' + + 'function which returns an object of state variables.' + ) : invariant(typeof partialState === 'object' || + typeof partialState === 'function' || + partialState == null)); + if ("production" !== "development") { + ("production" !== "development" ? warning( + partialState != null, + 'setState(...): You passed an undefined or null state object; ' + + 'instead, use forceUpdate().' + ) : null); + } + ReactUpdateQueue.enqueueSetState(this, partialState); + if (callback) { + ReactUpdateQueue.enqueueCallback(this, callback); + } +}; + +/** + * Forces an update. This should only be invoked when it is known with + * certainty that we are **not** in a DOM transaction. + * + * You may want to call this when you know that some deeper aspect of the + * component's state has changed but `setState` was not called. + * + * This will not invoke `shouldComponentUpdate`, but it will invoke + * `componentWillUpdate` and `componentDidUpdate`. + * + * @param {?function} callback Called after update is complete. + * @final + * @protected + */ +ReactComponent.prototype.forceUpdate = function(callback) { + ReactUpdateQueue.enqueueForceUpdate(this); + if (callback) { + ReactUpdateQueue.enqueueCallback(this, callback); + } +}; + +/** + * Deprecated APIs. These APIs used to exist on classic React classes but since + * we would like to deprecate them, we're not going to move them over to this + * modern base class. Instead, we define a getter that warns if it's accessed. + */ +if ("production" !== "development") { + var deprecatedAPIs = { + getDOMNode: 'getDOMNode', + isMounted: 'isMounted', + replaceProps: 'replaceProps', + replaceState: 'replaceState', + setProps: 'setProps' + }; + var defineDeprecationWarning = function(methodName, displayName) { + try { + Object.defineProperty(ReactComponent.prototype, methodName, { + get: function() { + ("production" !== "development" ? warning( + false, + '%s(...) is deprecated in plain JavaScript React classes.', + displayName + ) : null); + return undefined; + } + }); + } catch (x) { + // IE will fail on defineProperty (es5-shim/sham too) + } + }; + for (var fnName in deprecatedAPIs) { + if (deprecatedAPIs.hasOwnProperty(fnName)) { + defineDeprecationWarning(fnName, deprecatedAPIs[fnName]); } } } -function validateMethodOverride(proto, name) { - var specPolicy = ReactCompositeComponentInterface.hasOwnProperty(name) ? - ReactCompositeComponentInterface[name] : - null; +module.exports = ReactComponent; - // Disallow overriding of base class methods unless explicitly allowed. - if (ReactCompositeComponentMixin.hasOwnProperty(name)) { - ("production" !== "development" ? invariant( - specPolicy === SpecPolicy.OVERRIDE_BASE, - 'ReactCompositeComponentInterface: You are attempting to override ' + - '`%s` from your class specification. Ensure that your method names ' + - 'do not overlap with React methods.', - name - ) : invariant(specPolicy === SpecPolicy.OVERRIDE_BASE)); - } +},{"150":150,"171":171,"99":99}],40:[function(_dereq_,module,exports){ +/** + * Copyright 2013-2015, 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 ReactComponentBrowserEnvironment + */ - // Disallow defining methods more than once unless explicitly allowed. - if (proto.hasOwnProperty(name)) { - ("production" !== "development" ? invariant( - specPolicy === SpecPolicy.DEFINE_MANY || - specPolicy === SpecPolicy.DEFINE_MANY_MERGED, - 'ReactCompositeComponentInterface: You are attempting to define ' + - '`%s` on your component more than once. This conflict may be due ' + - 'to a mixin.', - name - ) : invariant(specPolicy === SpecPolicy.DEFINE_MANY || - specPolicy === SpecPolicy.DEFINE_MANY_MERGED)); - } -} +/*jslint evil: true */ -function validateLifeCycleOnReplaceState(instance) { - var compositeLifeCycleState = instance._compositeLifeCycleState; - ("production" !== "development" ? invariant( - instance.isMounted() || - compositeLifeCycleState === CompositeLifeCycle.MOUNTING, - 'replaceState(...): Can only update a mounted or mounting component.' - ) : invariant(instance.isMounted() || - compositeLifeCycleState === CompositeLifeCycle.MOUNTING)); - ("production" !== "development" ? invariant( - ReactCurrentOwner.current == null, - 'replaceState(...): Cannot update during an existing state transition ' + - '(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.' - ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING)); -} +'use strict'; + +var ReactDOMIDOperations = _dereq_(50); +var ReactMount = _dereq_(77); /** - * Mixin helper which handles policy validation and reserved - * specification keys when building `ReactCompositeComponent` classses. + * Abstracts away all functionality of the reconciler that requires knowledge of + * the browser context. TODO: These callers should be refactored to avoid the + * need for this injection. */ -function mixSpecIntoComponent(Constructor, spec) { - if (!spec) { - return; - } +var ReactComponentBrowserEnvironment = { - ("production" !== "development" ? invariant( - !ReactLegacyElement.isValidFactory(spec), - 'ReactCompositeComponent: You\'re attempting to ' + - 'use a component class as a mixin. Instead, just use a regular object.' - ) : invariant(!ReactLegacyElement.isValidFactory(spec))); - ("production" !== "development" ? invariant( - !ReactElement.isValidElement(spec), - 'ReactCompositeComponent: You\'re attempting to ' + - 'use a component as a mixin. Instead, just use a regular object.' - ) : invariant(!ReactElement.isValidElement(spec))); + processChildrenUpdates: + ReactDOMIDOperations.dangerouslyProcessChildrenUpdates, - var proto = Constructor.prototype; + replaceNodeWithMarkupByID: + ReactDOMIDOperations.dangerouslyReplaceNodeWithMarkupByID, - // 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); + /** + * If a particular environment requires that some resources be cleaned up, + * specify this in the injected Mixin. In the DOM, we would likely want to + * purge any cached node ID lookups. + * + * @private + */ + unmountIDFromEnvironment: function(rootNodeID) { + ReactMount.purgeID(rootNodeID); } - for (var name in spec) { - if (!spec.hasOwnProperty(name)) { - continue; - } +}; - if (name === MIXINS_KEY) { - // We have already handled mixins in a special case above - continue; - } +module.exports = ReactComponentBrowserEnvironment; - var property = spec[name]; - validateMethodOverride(proto, name); +},{"50":50,"77":77}],41:[function(_dereq_,module,exports){ +/** + * Copyright 2014-2015, 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 ReactComponentEnvironment + */ - if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) { - RESERVED_SPEC_KEYS[name](Constructor, property); - } else { - // Setup methods on prototype: - // The following member methods should not be automatically bound: - // 1. Expected ReactCompositeComponent methods (in the "interface"). - // 2. Overridden methods (that were mixed in). - var isCompositeComponentMethod = - ReactCompositeComponentInterface.hasOwnProperty(name); - var isAlreadyDefined = proto.hasOwnProperty(name); - var markedDontBind = property && property.__reactDontBind; - var isFunction = typeof property === 'function'; - var shouldAutoBind = - isFunction && - !isCompositeComponentMethod && - !isAlreadyDefined && - !markedDontBind; +'use strict'; - if (shouldAutoBind) { - if (!proto.__reactAutoBindMap) { - proto.__reactAutoBindMap = {}; - } - proto.__reactAutoBindMap[name] = property; - proto[name] = property; - } else { - if (isAlreadyDefined) { - var specPolicy = ReactCompositeComponentInterface[name]; +var invariant = _dereq_(150); - // These cases should already be caught by validateMethodOverride - ("production" !== "development" ? invariant( - isCompositeComponentMethod && ( - specPolicy === SpecPolicy.DEFINE_MANY_MERGED || - specPolicy === SpecPolicy.DEFINE_MANY - ), - 'ReactCompositeComponent: Unexpected spec policy %s for key %s ' + - 'when mixing in component specs.', - specPolicy, - name - ) : invariant(isCompositeComponentMethod && ( - specPolicy === SpecPolicy.DEFINE_MANY_MERGED || - specPolicy === SpecPolicy.DEFINE_MANY - ))); +var injected = false; - // For methods which are defined more than once, call the existing - // methods before calling the new property, merging if appropriate. - if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) { - proto[name] = createMergedResultFunction(proto[name], property); - } else if (specPolicy === SpecPolicy.DEFINE_MANY) { - proto[name] = createChainedFunction(proto[name], property); - } - } else { - proto[name] = property; - if ("production" !== "development") { - // Add verbose displayName to the function, which helps when looking - // at profiling tools. - if (typeof property === 'function' && spec.displayName) { - proto[name].displayName = spec.displayName + '_' + name; - } - } - } - } - } - } -} +var ReactComponentEnvironment = { -function mixStaticSpecIntoComponent(Constructor, statics) { - if (!statics) { - return; - } - for (var name in statics) { - var property = statics[name]; - if (!statics.hasOwnProperty(name)) { - continue; - } + /** + * Optionally injectable environment dependent cleanup hook. (server vs. + * browser etc). Example: A browser system caches DOM nodes based on component + * ID and must remove that cache entry when this instance is unmounted. + */ + unmountIDFromEnvironment: null, - 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)); + /** + * Optionally injectable hook for swapping out mount images in the middle of + * the tree. + */ + replaceNodeWithMarkupByID: null, - var isInherited = name in Constructor; - ("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; + /** + * Optionally injectable hook for processing a queue of child updates. Will + * later move into MultiChildComponents. + */ + processChildrenUpdates: null, + + injection: { + injectEnvironment: function(environment) { + ("production" !== "development" ? invariant( + !injected, + 'ReactCompositeComponent: injectEnvironment() can only be called once.' + ) : invariant(!injected)); + ReactComponentEnvironment.unmountIDFromEnvironment = + environment.unmountIDFromEnvironment; + ReactComponentEnvironment.replaceNodeWithMarkupByID = + environment.replaceNodeWithMarkupByID; + ReactComponentEnvironment.processChildrenUpdates = + environment.processChildrenUpdates; + injected = true; + } } -} +}; + +module.exports = ReactComponentEnvironment; + +},{"150":150}],42:[function(_dereq_,module,exports){ /** - * Merge two objects, but throw if both contain the same key. + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. * - * @param {object} one The first object, which is mutated. - * @param {object} two The second object - * @return {object} one after it has been mutated to contain everything in two. - */ -function mergeObjectsWithNoDuplicateKeys(one, two) { - ("production" !== "development" ? invariant( - one && two && typeof one === 'object' && typeof two === 'object', - 'mergeObjectsWithNoDuplicateKeys(): Cannot merge non-objects' - ) : invariant(one && two && typeof one === 'object' && typeof two === 'object')); + * 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 +*/ - mapObject(two, function(value, key) { - ("production" !== "development" ? invariant( - one[key] === undefined, - 'mergeObjectsWithNoDuplicateKeys(): ' + - '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; - }); - return one; -} +'use strict'; + +var shallowEqual = _dereq_(166); /** - * Creates a function that invokes two functions and merges their return values. + * If your React component's render function is "pure", e.g. it will render the + * same result given the same props and state, provide this Mixin for a + * considerable performance boost. * - * @param {function} one Function to invoke first. - * @param {function} two Function to invoke second. - * @return {function} Function that invokes the two argument functions. - * @private + * Most React components have pure render functions. + * + * Example: + * + * var ReactComponentWithPureRenderMixin = + * require('ReactComponentWithPureRenderMixin'); + * React.createClass({ + * mixins: [ReactComponentWithPureRenderMixin], + * + * render: function() { + * return
foo
; + * } + * }); + * + * Note: This only checks shallow equality for props and state. If these contain + * complex data structures this mixin may have false-negatives for deeper + * differences. Only mixin to components which have simple props and state, or + * use `forceUpdate()` when you know deep data structures have changed. */ -function createMergedResultFunction(one, two) { - return function mergedResult() { - var a = one.apply(this, arguments); - var b = two.apply(this, arguments); - if (a == null) { - return b; - } else if (b == null) { - return a; - } - return mergeObjectsWithNoDuplicateKeys(a, b); - }; -} +var ReactComponentWithPureRenderMixin = { + shouldComponentUpdate: function(nextProps, nextState) { + return !shallowEqual(this.props, nextProps) || + !shallowEqual(this.state, nextState); + } +}; + +module.exports = ReactComponentWithPureRenderMixin; +},{"166":166}],43:[function(_dereq_,module,exports){ /** - * Creates a function that invokes two functions and ignores their return vales. + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. * - * @param {function} one Function to invoke first. - * @param {function} two Function to invoke second. - * @return {function} Function that invokes the two argument functions. - * @private + * 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 */ -function createChainedFunction(one, two) { - return function chainedFunction() { - one.apply(this, arguments); - two.apply(this, arguments); - }; + +'use strict'; + +var ReactComponentEnvironment = _dereq_(41); +var ReactContext = _dereq_(44); +var ReactCurrentOwner = _dereq_(45); +var ReactElement = _dereq_(63); +var ReactElementValidator = _dereq_(64); +var ReactInstanceMap = _dereq_(73); +var ReactLifeCycle = _dereq_(74); +var ReactNativeComponent = _dereq_(80); +var ReactPerf = _dereq_(82); +var ReactPropTypeLocations = _dereq_(85); +var ReactPropTypeLocationNames = _dereq_(84); +var ReactReconciler = _dereq_(89); +var ReactUpdates = _dereq_(100); + +var assign = _dereq_(29); +var emptyObject = _dereq_(130); +var invariant = _dereq_(150); +var shouldUpdateReactComponent = _dereq_(167); +var warning = _dereq_(171); + +function getDeclarationErrorAddendum(component) { + var owner = component._currentElement._owner || null; + if (owner) { + var name = owner.getName(); + if (name) { + return ' Check the render method of `' + name + '`.'; + } + } + return ''; } /** - * `ReactCompositeComponent` maintains an auxiliary life cycle state in - * `this._compositeLifeCycleState` (which can be null). + * ------------------ The Life-Cycle of a Composite Component ------------------ * - * This is different from the life cycle state maintained by `ReactComponent` in - * `this._lifeCycleState`. The following diagram shows how the states overlap in - * time. There are times when the CompositeLifeCycle is null - at those times it - * is only meaningful to look at ComponentLifeCycle alone. + * - constructor: Initialization of state. The instance is now retained. + * - componentWillMount + * - render + * - [children's constructors] + * - [children's componentWillMount and render] + * - [children's componentDidMount] + * - componentDidMount * - * Top Row: ReactComponent.ComponentLifeCycle - * Low Row: ReactComponent.CompositeLifeCycle + * Update Phases: + * - componentWillReceiveProps (only called if parent updated) + * - shouldComponentUpdate + * - componentWillUpdate + * - render + * - [children's constructors or receive props phases] + * - componentDidUpdate * - * +-------+---------------------------------+--------+ - * | UN | MOUNTED | UN | - * |MOUNTED| | MOUNTED| - * +-------+---------------------------------+--------+ - * | ^--------+ +-------+ +--------^ | - * | | | | | | | | - * | 0--|MOUNTING|-0-|RECEIVE|-0-| UN |--->0 | - * | | | |PROPS | |MOUNTING| | - * | | | | | | | | - * | | | | | | | | - * | +--------+ +-------+ +--------+ | - * | | | | - * +-------+---------------------------------+--------+ + * - componentWillUnmount + * - [children's componentWillUnmount] + * - [children destroyed] + * - (destroyed): The instance is now blank, released by React and ready for GC. + * + * ----------------------------------------------------------------------------- */ -var CompositeLifeCycle = keyMirror({ - /** - * Components in the process of being mounted respond to state changes - * differently. - */ - MOUNTING: null, - /** - * Components in the process of being unmounted are guarded against state - * changes. - */ - UNMOUNTING: null, - /** - * Components that are mounted and receiving new props respond to state - * changes differently. - */ - RECEIVING_PROPS: null -}); + +/** + * An incrementing ID assigned to each component when it is mounted. This is + * used to enforce the order in which `ReactUpdates` updates dirty components. + * + * @private + */ +var nextMountID = 1; /** * @lends {ReactCompositeComponent.prototype} @@ -6494,29 +6718,24 @@ var ReactCompositeComponentMixin = { * @internal */ 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); + this._currentElement = element; + this._rootNodeID = null; + this._instance = null; - this.state = null; - this._pendingState = null; + // See ReactUpdateQueue + this._pendingElement = null; + this._pendingStateQueue = null; + this._pendingReplaceState = false; + this._pendingForceUpdate = false; - // This is the public post-processed context. The real context and pending - // context lives on the element. - this.context = null; + this._renderedComponent = null; - this._compositeLifeCycleState = null; - }, + this._context = null; + this._mountOrder = 0; + this._isTopLevel = false; - /** - * Checks whether or not this composite component is mounted. - * @return {boolean} True if mounted, false otherwise. - * @protected - * @final - */ - isMounted: function() { - return ReactComponent.Mixin.isMounted.call(this) && - this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING; + // See ReactUpdates and ReactUpdateQueue. + this._pendingCallbacks = null; }, /** @@ -6524,68 +6743,137 @@ var ReactCompositeComponentMixin = { * * @param {string} rootID DOM ID of the root node. * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction - * @param {number} mountDepth number of components in the owner hierarchy * @return {?string} Rendered markup to be inserted into the DOM. * @final * @internal */ - mountComponent: ReactPerf.measure( - 'ReactCompositeComponent', - 'mountComponent', - function(rootID, transaction, mountDepth) { - ReactComponent.Mixin.mountComponent.call( - this, - rootID, - transaction, - mountDepth - ); - this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING; + mountComponent: function(rootID, transaction, context) { + this._context = context; + this._mountOrder = nextMountID++; + this._rootNodeID = rootID; - if (this.__reactAutoBindMap) { - this._bindAutoBindMethods(); - } + var publicProps = this._processProps(this._currentElement.props); + var publicContext = this._processContext(this._currentElement._context); - this.context = this._processContext(this._currentElement._context); - this.props = this._processProps(this.props); + var Component = ReactNativeComponent.getComponentClassForElement( + this._currentElement + ); - this.state = this.getInitialState ? this.getInitialState() : null; - ("production" !== "development" ? invariant( - typeof this.state === 'object' && !Array.isArray(this.state), - '%s.getInitialState(): must return an object or null', - this.constructor.displayName || 'ReactCompositeComponent' - ) : invariant(typeof this.state === 'object' && !Array.isArray(this.state))); + // Initialize the public class + var inst = new Component(publicProps, publicContext); - this._pendingState = null; - this._pendingForceUpdate = false; + if ("production" !== "development") { + // This will throw later in _renderValidatedComponent, but add an early + // warning now to help debugging + ("production" !== "development" ? warning( + inst.render != null, + '%s(...): No `render` method found on the returned component ' + + 'instance: you may have forgotten to define `render` in your ' + + 'component or you may have accidentally tried to render an element ' + + 'whose type is a function that isn\'t a React component.', + Component.displayName || Component.name || 'Component' + ) : null); + } + + // These should be set up in the constructor, but as a convenience for + // simpler class abstractions, we set them up after the fact. + inst.props = publicProps; + inst.context = publicContext; + inst.refs = emptyObject; + + this._instance = inst; + + // Store a reference from the instance back to the internal representation + ReactInstanceMap.set(inst, this); + + if ("production" !== "development") { + this._warnIfContextsDiffer(this._currentElement._context, context); + } + + if ("production" !== "development") { + // Since plain JS classes are defined without any special initialization + // logic, we can not catch common errors early. Therefore, we have to + // catch them here, at initialization time, instead. + ("production" !== "development" ? warning( + !inst.getInitialState || + inst.getInitialState.isReactClassApproved, + 'getInitialState was defined on %s, a plain JavaScript class. ' + + 'This is only supported for classes created using React.createClass. ' + + 'Did you mean to define a state property instead?', + this.getName() || 'a component' + ) : null); + ("production" !== "development" ? warning( + !inst.propTypes, + 'propTypes was defined as an instance property on %s. Use a static ' + + 'property to define propTypes instead.', + this.getName() || 'a component' + ) : null); + ("production" !== "development" ? warning( + !inst.contextTypes, + 'contextTypes was defined as an instance property on %s. Use a ' + + 'static property to define contextTypes instead.', + this.getName() || 'a component' + ) : null); + ("production" !== "development" ? warning( + typeof inst.componentShouldUpdate !== 'function', + '%s has a method called ' + + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + + 'The name is phrased as a question because the function is ' + + 'expected to return a value.', + (this.getName() || 'A component') + ) : null); + } + + var initialState = inst.state; + if (initialState === undefined) { + inst.state = initialState = null; + } + ("production" !== "development" ? invariant( + typeof initialState === 'object' && !Array.isArray(initialState), + '%s.state: must be set to an object or null', + this.getName() || 'ReactCompositeComponent' + ) : invariant(typeof initialState === 'object' && !Array.isArray(initialState))); - if (this.componentWillMount) { - this.componentWillMount(); + this._pendingStateQueue = null; + this._pendingReplaceState = false; + this._pendingForceUpdate = false; + + var renderedElement; + + var previouslyMounting = ReactLifeCycle.currentlyMountingInstance; + ReactLifeCycle.currentlyMountingInstance = this; + try { + if (inst.componentWillMount) { + inst.componentWillMount(); // When mounting, calls to `setState` by `componentWillMount` will set - // `this._pendingState` without triggering a re-render. - if (this._pendingState) { - this.state = this._pendingState; - this._pendingState = null; + // `this._pendingStateQueue` without triggering a re-render. + if (this._pendingStateQueue) { + inst.state = this._processPendingState(inst.props, inst.context); } } - this._renderedComponent = instantiateReactComponent( - this._renderValidatedComponent(), - this._currentElement.type // The wrapping type - ); + renderedElement = this._renderValidatedComponent(); + } finally { + ReactLifeCycle.currentlyMountingInstance = previouslyMounting; + } - // Done with mounting, `setState` will now trigger UI changes. - this._compositeLifeCycleState = null; - var markup = this._renderedComponent.mountComponent( - rootID, - transaction, - mountDepth + 1 - ); - if (this.componentDidMount) { - transaction.getReactMountReady().enqueue(this.componentDidMount, this); - } - return markup; + this._renderedComponent = this._instantiateReactComponent( + renderedElement, + this._currentElement.type // The wrapping type + ); + + var markup = ReactReconciler.mountComponent( + this._renderedComponent, + rootID, + transaction, + this._processChildContext(context) + ); + if (inst.componentDidMount) { + transaction.getReactMountReady().enqueue(inst.componentDidMount, inst); } - ), + + return markup; + }, /** * Releases any resources allocated by `mountComponent`. @@ -6594,83 +6882,88 @@ var ReactCompositeComponentMixin = { * @internal */ unmountComponent: function() { - this._compositeLifeCycleState = CompositeLifeCycle.UNMOUNTING; - if (this.componentWillUnmount) { - this.componentWillUnmount(); + var inst = this._instance; + + if (inst.componentWillUnmount) { + var previouslyUnmounting = ReactLifeCycle.currentlyUnmountingInstance; + ReactLifeCycle.currentlyUnmountingInstance = this; + try { + inst.componentWillUnmount(); + } finally { + ReactLifeCycle.currentlyUnmountingInstance = previouslyUnmounting; + } } - this._compositeLifeCycleState = null; - this._renderedComponent.unmountComponent(); + ReactReconciler.unmountComponent(this._renderedComponent); this._renderedComponent = null; - ReactComponent.Mixin.unmountComponent.call(this); + // Reset pending fields + this._pendingStateQueue = null; + this._pendingReplaceState = false; + this._pendingForceUpdate = false; + this._pendingCallbacks = null; + this._pendingElement = null; + + // These fields do not really need to be reset since this object is no + // longer accessible. + this._context = null; + this._rootNodeID = null; + + // Delete the reference from the instance to this internal representation + // which allow the internals to be properly cleaned up even if the user + // leaks a reference to the public instance. + ReactInstanceMap.remove(inst); - // Some existing components rely on this.props even after they've been + // Some existing components rely on inst.props even after they've been // destroyed (in event handlers). - // TODO: this.props = null; - // TODO: this.state = null; + // TODO: inst.props = null; + // TODO: inst.state = null; + // TODO: inst.context = null; }, /** - * Sets a subset of the state. Always use this or `replaceState` to mutate - * state. You should treat `this.state` as immutable. + * Schedule a partial update to the props. Only used for internal testing. * - * There is no guarantee that `this.state` will be immediately updated, so - * accessing `this.state` after calling this method may return the old value. - * - * There is no guarantee that calls to `setState` will run synchronously, - * as they may eventually be batched together. You can provide an optional - * callback that will be executed when the call to setState is actually - * completed. - * - * @param {object} partialState Next partial state to be merged with state. - * @param {?function} callback Called after state is updated. + * @param {object} partialProps Subset of the next props. + * @param {?function} callback Called after props are updated. * @final - * @protected + * @internal */ - setState: function(partialState, callback) { - ("production" !== "development" ? invariant( - typeof partialState === 'object' || partialState == null, - 'setState(...): takes an object of state variables to update.' - ) : invariant(typeof partialState === 'object' || partialState == null)); - if ("production" !== "development"){ - ("production" !== "development" ? warning( - partialState != null, - 'setState(...): You passed an undefined or null state object; ' + - 'instead, use forceUpdate().' - ) : null); - } - // Merge with `_pendingState` if it exists, otherwise with existing state. - this.replaceState( - assign({}, this._pendingState || this.state, partialState), - callback + _setPropsInternal: function(partialProps, callback) { + // This is a deoptimized path. We optimize for always having an 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); }, /** - * Replaces all of the state. Always use this or `setState` to mutate state. - * You should treat `this.state` as immutable. - * - * There is no guarantee that `this.state` will be immediately updated, so - * accessing `this.state` after calling this method may return the old value. + * Filters the context object to only contain keys specified in + * `contextTypes` * - * @param {object} completeState Next state. - * @param {?function} callback Called after state is updated. - * @final - * @protected + * @param {object} context + * @return {?object} + * @private */ - replaceState: function(completeState, callback) { - validateLifeCycleOnReplaceState(this); - this._pendingState = completeState; - if (this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING) { - // If we're in a componentWillMount handler, don't enqueue a rerender - // because ReactUpdates assumes we're in a browser context (which is wrong - // for server rendering) and we're about to do a render anyway. - // TODO: The callback here is ignored when setState is called from - // componentWillMount. Either fix it or disallow doing so completely in - // favor of getInitialState. - ReactUpdates.enqueueUpdate(this, callback); + _maskContext: function(context) { + var maskedContext = null; + // This really should be getting the component class for the element, + // but we know that we're not going to need it for built-ins. + if (typeof this._currentElement.type === 'string') { + return emptyObject; } + var contextTypes = this._currentElement.type.contextTypes; + if (!contextTypes) { + return emptyObject; + } + maskedContext = {}; + for (var contextName in contextTypes) { + maskedContext[contextName] = context[contextName]; + } + return maskedContext; }, /** @@ -6682,16 +6975,14 @@ var ReactCompositeComponentMixin = { * @private */ _processContext: function(context) { - var maskedContext = null; - var contextTypes = this.constructor.contextTypes; - if (contextTypes) { - maskedContext = {}; - for (var contextName in contextTypes) { - maskedContext[contextName] = context[contextName]; - } - if ("production" !== "development") { + var maskedContext = this._maskContext(context); + if ("production" !== "development") { + var Component = ReactNativeComponent.getComponentClassForElement( + this._currentElement + ); + if (Component.contextTypes) { this._checkPropTypes( - contextTypes, + Component.contextTypes, maskedContext, ReactPropTypeLocations.context ); @@ -6706,29 +6997,29 @@ var ReactCompositeComponentMixin = { * @private */ _processChildContext: function(currentContext) { - var childContext = this.getChildContext && this.getChildContext(); - var displayName = this.constructor.displayName || 'ReactCompositeComponent'; + var inst = this._instance; + var childContext = inst.getChildContext && inst.getChildContext(); if (childContext) { ("production" !== "development" ? invariant( - typeof this.constructor.childContextTypes === 'object', + typeof inst.constructor.childContextTypes === 'object', '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', - displayName - ) : invariant(typeof this.constructor.childContextTypes === 'object')); + this.getName() || 'ReactCompositeComponent' + ) : invariant(typeof inst.constructor.childContextTypes === 'object')); if ("production" !== "development") { this._checkPropTypes( - this.constructor.childContextTypes, + inst.constructor.childContextTypes, childContext, ReactPropTypeLocations.childContext ); } for (var name in childContext) { ("production" !== "development" ? invariant( - name in this.constructor.childContextTypes, + name in inst.constructor.childContextTypes, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', - displayName, + this.getName() || 'ReactCompositeComponent', name - ) : invariant(name in this.constructor.childContextTypes)); + ) : invariant(name in inst.constructor.childContextTypes)); } return assign({}, currentContext, childContext); } @@ -6746,9 +7037,15 @@ var ReactCompositeComponentMixin = { */ _processProps: function(newProps) { if ("production" !== "development") { - var propTypes = this.constructor.propTypes; - if (propTypes) { - this._checkPropTypes(propTypes, newProps, ReactPropTypeLocations.prop); + var Component = ReactNativeComponent.getComponentClassForElement( + this._currentElement + ); + if (Component.propTypes) { + this._checkPropTypes( + Component.propTypes, + newProps, + ReactPropTypeLocations.prop + ); } } return newProps; @@ -6765,101 +7062,236 @@ var ReactCompositeComponentMixin = { _checkPropTypes: function(propTypes, props, location) { // TODO: Stop validating prop types here and only use the element // validation. - var componentName = this.constructor.displayName; + var componentName = this.getName(); for (var propName in propTypes) { if (propTypes.hasOwnProperty(propName)) { - var error = - propTypes[propName](props, propName, componentName, location); + var error; + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + ("production" !== "development" ? invariant( + typeof propTypes[propName] === 'function', + '%s: %s type `%s` is invalid; it must be a function, usually ' + + 'from React.PropTypes.', + componentName || 'React class', + ReactPropTypeLocationNames[location], + propName + ) : invariant(typeof propTypes[propName] === 'function')); + error = propTypes[propName](props, propName, componentName, location); + } catch (ex) { + error = ex; + } if (error instanceof Error) { // We may want to extend this logic for similar errors in - // renderComponent calls, so I'm abstracting it away into + // React.render calls, so I'm abstracting it away into // a function to minimize refactoring in the future var addendum = getDeclarationErrorAddendum(this); - ("production" !== "development" ? warning(false, error.message + addendum) : null); + + if (location === ReactPropTypeLocations.prop) { + // Preface gives us something to blacklist in warning module + ("production" !== "development" ? warning( + false, + 'Failed Composite propType: %s%s', + error.message, + addendum + ) : null); + } else { + ("production" !== "development" ? warning( + false, + 'Failed Context Types: %s%s', + error.message, + addendum + ) : null); + } } } } }, + receiveComponent: function(nextElement, transaction, nextContext) { + var prevElement = this._currentElement; + var prevContext = this._context; + + this._pendingElement = null; + + this.updateComponent( + transaction, + prevElement, + nextElement, + prevContext, + nextContext + ); + }, + /** - * If any of `_pendingElement`, `_pendingState`, or `_pendingForceUpdate` + * If any of `_pendingElement`, `_pendingStateQueue`, or `_pendingForceUpdate` * is set, update the component. * * @param {ReactReconcileTransaction} transaction * @internal */ performUpdateIfNecessary: function(transaction) { - var compositeLifeCycleState = this._compositeLifeCycleState; - // Do not trigger a state transition if we are in the middle of mounting or - // receiving props because both of those will already be doing this. - if (compositeLifeCycleState === CompositeLifeCycle.MOUNTING || - compositeLifeCycleState === CompositeLifeCycle.RECEIVING_PROPS) { - return; + if (this._pendingElement != null) { + ReactReconciler.receiveComponent( + this, + this._pendingElement || this._currentElement, + transaction, + this._context + ); } - if (this._pendingElement == null && - this._pendingState == null && - !this._pendingForceUpdate) { - return; + if (this._pendingStateQueue !== null || this._pendingForceUpdate) { + if ("production" !== "development") { + ReactElementValidator.checkAndWarnForMutatedProps( + this._currentElement + ); + } + + this.updateComponent( + transaction, + this._currentElement, + this._currentElement, + this._context, + this._context + ); } + }, - var nextContext = this.context; - var nextProps = this.props; - 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) { - this.componentWillReceiveProps(nextProps, nextContext); - } + /** + * Compare two contexts, warning if they are different + * TODO: Remove this check when owner-context is removed + */ + _warnIfContextsDiffer: function(ownerBasedContext, parentBasedContext) { + ownerBasedContext = this._maskContext(ownerBasedContext); + parentBasedContext = this._maskContext(parentBasedContext); + var parentKeys = Object.keys(parentBasedContext).sort(); + var displayName = this.getName() || 'ReactCompositeComponent'; + for (var i = 0; i < parentKeys.length; i++) { + var key = parentKeys[i]; + ("production" !== "development" ? warning( + ownerBasedContext[key] === parentBasedContext[key], + 'owner-based and parent-based contexts differ ' + + '(values: `%s` vs `%s`) for key (%s) while mounting %s ' + + '(see: http://fb.me/react-context-by-parent)', + ownerBasedContext[key], + parentBasedContext[key], + key, + displayName + ) : null); } + }, + + /** + * Perform an update to a mounted component. The componentWillReceiveProps and + * shouldComponentUpdate methods are called, then (assuming the update isn't + * skipped) the remaining update lifecycle methods are called and the DOM + * representation is updated. + * + * By default, this implements React's rendering and reconciliation algorithm. + * Sophisticated clients may wish to override this. + * + * @param {ReactReconcileTransaction} transaction + * @param {ReactElement} prevParentElement + * @param {ReactElement} nextParentElement + * @internal + * @overridable + */ + updateComponent: function( + transaction, + prevParentElement, + nextParentElement, + prevUnmaskedContext, + nextUnmaskedContext + ) { + var inst = this._instance; - this._compositeLifeCycleState = null; + var nextContext = inst.context; + var nextProps = inst.props; - var nextState = this._pendingState || this.state; - this._pendingState = null; + // Distinguish between a props update versus a simple state update + if (prevParentElement !== nextParentElement) { + nextContext = this._processContext(nextParentElement._context); + nextProps = this._processProps(nextParentElement.props); + + if ("production" !== "development") { + if (nextUnmaskedContext != null) { + this._warnIfContextsDiffer( + nextParentElement._context, + nextUnmaskedContext + ); + } + } + + // An update here will schedule an update but immediately set + // _pendingStateQueue which will ensure that any state updates gets + // immediately reconciled instead of waiting for the next batch. + + if (inst.componentWillReceiveProps) { + inst.componentWillReceiveProps(nextProps, nextContext); + } + } + + var nextState = this._processPendingState(nextProps, nextContext); var shouldUpdate = this._pendingForceUpdate || - !this.shouldComponentUpdate || - this.shouldComponentUpdate(nextProps, nextState, nextContext); + !inst.shouldComponentUpdate || + inst.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.' - ); - } + ("production" !== "development" ? warning( + typeof shouldUpdate !== 'undefined', + '%s.shouldComponentUpdate(): Returned undefined instead of a ' + + 'boolean value. Make sure to return true or false.', + this.getName() || 'ReactCompositeComponent' + ) : null); } if (shouldUpdate) { this._pendingForceUpdate = false; // Will set `this.props`, `this.state` and `this.context`. this._performComponentUpdate( - nextElement, + nextParentElement, nextProps, nextState, nextContext, - transaction + transaction, + nextUnmaskedContext ); } 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; + // to set props and state but we shortcut the rest of the update. + this._currentElement = nextParentElement; + this._context = nextUnmaskedContext; + inst.props = nextProps; + inst.state = nextState; + inst.context = nextContext; + } + }, + + _processPendingState: function(props, context) { + var inst = this._instance; + var queue = this._pendingStateQueue; + var replace = this._pendingReplaceState; + this._pendingReplaceState = false; + this._pendingStateQueue = null; + + if (!queue) { + return inst.state; + } - // Owner cannot change because shouldUpdateReactComponent doesn't allow - // it. TODO: Remove this._owner completely. - this._owner = nextElement._owner; + var nextState = assign({}, replace ? queue[0] : inst.state); + for (var i = replace ? 1 : 0; i < queue.length; i++) { + var partial = queue[i]; + assign( + nextState, + typeof partial === 'function' ? + partial.call(inst, nextState, props, context) : + partial + ); } + + return nextState; }, /** @@ -6871,6 +7303,7 @@ var ReactCompositeComponentMixin = { * @param {?object} nextState Next object to set as state. * @param {?object} nextContext Next public object to set as context. * @param {ReactReconcileTransaction} transaction + * @param {?object} unmaskedContext * @private */ _performComponentUpdate: function( @@ -6878,336 +7311,211 @@ var ReactCompositeComponentMixin = { nextProps, nextState, nextContext, - transaction + transaction, + unmaskedContext ) { - var prevElement = this._currentElement; - var prevProps = this.props; - var prevState = this.state; - var prevContext = this.context; + var inst = this._instance; + + var prevProps = inst.props; + var prevState = inst.state; + var prevContext = inst.context; - if (this.componentWillUpdate) { - this.componentWillUpdate(nextProps, nextState, nextContext); + if (inst.componentWillUpdate) { + inst.componentWillUpdate(nextProps, nextState, nextContext); } this._currentElement = nextElement; - this.props = nextProps; - this.state = nextState; - this.context = nextContext; + this._context = unmaskedContext; + inst.props = nextProps; + inst.state = nextState; + inst.context = nextContext; - // Owner cannot change because shouldUpdateReactComponent doesn't allow - // it. TODO: Remove this._owner completely. - this._owner = nextElement._owner; - - this.updateComponent( - transaction, - prevElement - ); + this._updateRenderedComponent(transaction, unmaskedContext); - if (this.componentDidUpdate) { + if (inst.componentDidUpdate) { transaction.getReactMountReady().enqueue( - this.componentDidUpdate.bind(this, prevProps, prevState, prevContext), - this + inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), + inst ); } }, - 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 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, - nextElement, - transaction - ); - }, - /** - * Updates the component's currently mounted DOM representation. - * - * By default, this implements React's rendering and reconciliation algorithm. - * Sophisticated clients may wish to override this. + * Call the component's `render` method and update the DOM accordingly. * * @param {ReactReconcileTransaction} transaction - * @param {ReactElement} prevElement - * @internal - * @overridable - */ - updateComponent: ReactPerf.measure( - 'ReactCompositeComponent', - 'updateComponent', - function(transaction, prevParentElement) { - ReactComponent.Mixin.updateComponent.call( - this, - transaction, - prevParentElement - ); - - var prevComponentInstance = this._renderedComponent; - 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( - nextElement, - this._currentElement.type - ); - var nextMarkup = this._renderedComponent.mountComponent( - thisID, - transaction, - this._mountDepth + 1 - ); - ReactComponent.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID( - prevComponentID, - nextMarkup - ); - } + * @internal + */ + _updateRenderedComponent: function(transaction, context) { + var prevComponentInstance = this._renderedComponent; + var prevRenderedElement = prevComponentInstance._currentElement; + var nextRenderedElement = this._renderValidatedComponent(); + if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) { + ReactReconciler.receiveComponent( + prevComponentInstance, + nextRenderedElement, + transaction, + this._processChildContext(context) + ); + } else { + // These two IDs are actually the same! But nothing should rely on that. + var thisID = this._rootNodeID; + var prevComponentID = prevComponentInstance._rootNodeID; + ReactReconciler.unmountComponent(prevComponentInstance); + + this._renderedComponent = this._instantiateReactComponent( + nextRenderedElement, + this._currentElement.type + ); + var nextMarkup = ReactReconciler.mountComponent( + this._renderedComponent, + thisID, + transaction, + context + ); + this._replaceNodeWithMarkupByID(prevComponentID, nextMarkup); } - ), + }, /** - * Forces an update. This should only be invoked when it is known with - * certainty that we are **not** in a DOM transaction. - * - * You may want to call this when you know that some deeper aspect of the - * component's state has changed but `setState` was not called. - * - * This will not invoke `shouldUpdateComponent`, but it will invoke - * `componentWillUpdate` and `componentDidUpdate`. - * - * @param {?function} callback Called after update is complete. - * @final * @protected */ - forceUpdate: function(callback) { - var compositeLifeCycleState = this._compositeLifeCycleState; - ("production" !== "development" ? invariant( - this.isMounted() || - compositeLifeCycleState === CompositeLifeCycle.MOUNTING, - 'forceUpdate(...): Can only force an update on mounted or mounting ' + - 'components.' - ) : invariant(this.isMounted() || - compositeLifeCycleState === CompositeLifeCycle.MOUNTING)); - ("production" !== "development" ? invariant( - compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING && - ReactCurrentOwner.current == null, - 'forceUpdate(...): Cannot force an update while unmounting component ' + - 'or within a `render` function.' - ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING && - ReactCurrentOwner.current == null)); - this._pendingForceUpdate = true; - ReactUpdates.enqueueUpdate(this, callback); + _replaceNodeWithMarkupByID: function(prevComponentID, nextMarkup) { + ReactComponentEnvironment.replaceNodeWithMarkupByID( + prevComponentID, + nextMarkup + ); }, /** - * @private + * @protected */ - _renderValidatedComponent: ReactPerf.measure( - 'ReactCompositeComponent', - '_renderValidatedComponent', - function() { - var renderedComponent; - var previousContext = ReactContext.current; - ReactContext.current = this._processChildContext( - this._currentElement._context - ); - ReactCurrentOwner.current = this; - try { - renderedComponent = this.render(); - if (renderedComponent === null || renderedComponent === false) { - renderedComponent = ReactEmptyComponent.getEmptyComponent(); - ReactEmptyComponent.registerNullComponentID(this._rootNodeID); - } else { - ReactEmptyComponent.deregisterNullComponentID(this._rootNodeID); - } - } finally { - ReactContext.current = previousContext; - ReactCurrentOwner.current = null; + _renderValidatedComponentWithoutOwnerOrContext: function() { + var inst = this._instance; + var renderedComponent = inst.render(); + if ("production" !== "development") { + // We allow auto-mocks to proceed as if they're returning null. + if (typeof renderedComponent === 'undefined' && + inst.render._isMockFunction) { + // This is probably bad practice. Consider warning here and + // deprecating this convenience. + renderedComponent = null; } - ("production" !== "development" ? invariant( - 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(ReactElement.isValidElement(renderedComponent))); - return renderedComponent; } - ), + + return renderedComponent; + }, /** * @private */ - _bindAutoBindMethods: function() { - for (var autoBindKey in this.__reactAutoBindMap) { - if (!this.__reactAutoBindMap.hasOwnProperty(autoBindKey)) { - continue; - } - var method = this.__reactAutoBindMap[autoBindKey]; - this[autoBindKey] = this._bindAutoBindMethod(ReactErrorUtils.guard( - method, - this.constructor.displayName + '.' + autoBindKey - )); + _renderValidatedComponent: function() { + var renderedComponent; + var previousContext = ReactContext.current; + ReactContext.current = this._processChildContext( + this._currentElement._context + ); + ReactCurrentOwner.current = this; + try { + renderedComponent = + this._renderValidatedComponentWithoutOwnerOrContext(); + } finally { + ReactContext.current = previousContext; + ReactCurrentOwner.current = null; } + ("production" !== "development" ? invariant( + // TODO: An `isValidNode` function would probably be more appropriate + renderedComponent === null || renderedComponent === false || + ReactElement.isValidElement(renderedComponent), + '%s.render(): A valid ReactComponent must be returned. You may have ' + + 'returned undefined, an array or some other invalid object.', + this.getName() || 'ReactCompositeComponent' + ) : invariant(// TODO: An `isValidNode` function would probably be more appropriate + renderedComponent === null || renderedComponent === false || + ReactElement.isValidElement(renderedComponent))); + return renderedComponent; }, /** - * Binds a method to the component. + * Lazily allocates the refs object and stores `component` as `ref`. * - * @param {function} method Method to be bound. + * @param {string} ref Reference name. + * @param {component} component Component to store as `ref`. + * @final * @private */ - _bindAutoBindMethod: function(method) { - var component = this; - 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 ) {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. - if (newThis !== component && newThis !== null) { - monitorCodeUse('react_bind_warning', { component: componentName }); - console.warn( - 'bind(): React component methods may only be bound to the ' + - 'component instance. See ' + componentName - ); - } else if (!args.length) { - monitorCodeUse('react_bind_warning', { component: componentName }); - console.warn( - 'bind(): You are binding a component method to the component. ' + - 'React does this for you automatically in a high-performance ' + - 'way, so you can safely remove this call. See ' + componentName - ); - return boundMethod; - } - var reboundMethod = _bind.apply(boundMethod, arguments); - reboundMethod.__reactBoundContext = component; - reboundMethod.__reactBoundMethod = method; - reboundMethod.__reactBoundArguments = args; - return reboundMethod; - }; - } - return boundMethod; - } -}; - -var ReactCompositeComponentBase = function() {}; -assign( - ReactCompositeComponentBase.prototype, - ReactComponent.Mixin, - ReactOwner.Mixin, - ReactPropTransferer.Mixin, - ReactCompositeComponentMixin -); - -/** - * Module for creating composite components. - * - * @class ReactCompositeComponent - * @extends ReactComponent - * @extends ReactOwner - * @extends ReactPropTransferer - */ -var ReactCompositeComponent = { - - LifeCycle: CompositeLifeCycle, - - Base: ReactCompositeComponentBase, + attachRef: function(ref, component) { + var inst = this.getPublicInstance(); + var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs; + refs[ref] = component.getPublicInstance(); + }, /** - * Creates a composite component class given a class specification. + * Detaches a reference name. * - * @param {object} spec Class specification (which must define `render`). - * @return {function} Component constructor function. - * @public + * @param {string} ref Name to dereference. + * @final + * @private */ - createClass: function(spec) { - 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; + detachRef: function(ref) { + var refs = this.getPublicInstance().refs; + delete refs[ref]; + }, - injectedMixins.forEach( - mixSpecIntoComponent.bind(null, Constructor) + /** + * Get a text description of the component that can be used to identify it + * in error messages. + * @return {string} The name or null. + * @internal + */ + getName: function() { + var type = this._currentElement.type; + var constructor = this._instance && this._instance.constructor; + return ( + type.displayName || (constructor && constructor.displayName) || + type.name || (constructor && constructor.name) || + null ); + }, - mixSpecIntoComponent(Constructor, spec); + /** + * Get the publicly accessible representation of this component - i.e. what + * is exposed by refs and returned by React.render. Can be null for stateless + * components. + * + * @return {ReactComponent} the public component instance. + * @internal + */ + getPublicInstance: function() { + return this._instance; + }, - // Initialize the defaultProps property after all mixins have been merged - if (Constructor.getDefaultProps) { - Constructor.defaultProps = Constructor.getDefaultProps(); - } + // Stub + _instantiateReactComponent: null - ("production" !== "development" ? invariant( - Constructor.prototype.render, - 'createClass(...): Class specification must implement a `render` method.' - ) : invariant(Constructor.prototype.render)); +}; - if ("production" !== "development") { - if (Constructor.prototype.componentShouldUpdate) { - monitorCodeUse( - 'react_component_should_update_warning', - { component: spec.displayName } - ); - console.warn( - (spec.displayName || 'A component') + ' has a method called ' + - 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + - 'The name is phrased as a question because the function is ' + - 'expected to return a value.' - ); - } - } +ReactPerf.measureMethods( + ReactCompositeComponentMixin, + 'ReactCompositeComponent', + { + mountComponent: 'mountComponent', + updateComponent: 'updateComponent', + _renderValidatedComponent: '_renderValidatedComponent' + } +); - // Reduce time spent doing lookups by setting these on the prototype. - for (var methodName in ReactCompositeComponentInterface) { - if (!Constructor.prototype[methodName]) { - Constructor.prototype[methodName] = null; - } - } +var ReactCompositeComponent = { - if ("production" !== "development") { - return ReactLegacyElement.wrapFactory( - ReactElementValidator.createFactory(Constructor) - ); - } - return ReactLegacyElement.wrapFactory( - ReactElement.createFactory(Constructor) - ); - }, + Mixin: ReactCompositeComponentMixin - injection: { - injectMixin: function(mixin) { - injectedMixins.push(mixin); - } - } }; module.exports = ReactCompositeComponent; -},{"./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){ +},{"100":100,"130":130,"150":150,"167":167,"171":171,"29":29,"41":41,"44":44,"45":45,"63":63,"64":64,"73":73,"74":74,"80":80,"82":82,"84":84,"85":85,"89":89}],44:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -7217,9 +7525,13 @@ module.exports = ReactCompositeComponent; * @providesModule ReactContext */ -"use strict"; +'use strict'; + +var assign = _dereq_(29); +var emptyObject = _dereq_(130); +var warning = _dereq_(171); -var assign = _dereq_("./Object.assign"); +var didWarn = false; /** * Keeps track of the current context. @@ -7233,7 +7545,7 @@ var ReactContext = { * @internal * @type {object} */ - current: {}, + current: emptyObject, /** * Temporarily extends the current context while executing scopedCallback. @@ -7252,6 +7564,16 @@ var ReactContext = { * @return {ReactComponent|array} */ withContext: function(newContext, scopedCallback) { + if ("production" !== "development") { + ("production" !== "development" ? warning( + didWarn, + 'withContext is deprecated and will be removed in a future version. ' + + 'Use a wrapper component with getChildContext instead.' + ) : null); + + didWarn = true; + } + var result; var previousContext = ReactContext.current; ReactContext.current = assign({}, previousContext, newContext); @@ -7267,9 +7589,9 @@ var ReactContext = { module.exports = ReactContext; -},{"./Object.assign":29}],42:[function(_dereq_,module,exports){ +},{"130":130,"171":171,"29":29}],45:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -7279,7 +7601,7 @@ module.exports = ReactContext; * @providesModule ReactCurrentOwner */ -"use strict"; +'use strict'; /** * Keeps track of the current owner. @@ -7301,9 +7623,9 @@ var ReactCurrentOwner = { module.exports = ReactCurrentOwner; -},{}],43:[function(_dereq_,module,exports){ +},{}],46:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -7314,13 +7636,12 @@ module.exports = ReactCurrentOwner; * @typechecks static-only */ -"use strict"; +'use strict'; -var ReactElement = _dereq_("./ReactElement"); -var ReactElementValidator = _dereq_("./ReactElementValidator"); -var ReactLegacyElement = _dereq_("./ReactLegacyElement"); +var ReactElement = _dereq_(63); +var ReactElementValidator = _dereq_(64); -var mapObject = _dereq_("./mapObject"); +var mapObject = _dereq_(158); /** * Create a factory that creates HTML tag elements. @@ -7330,13 +7651,9 @@ var mapObject = _dereq_("./mapObject"); */ function createDOMFactory(tag) { if ("production" !== "development") { - return ReactLegacyElement.markNonLegacyFactory( - ReactElementValidator.createFactory(tag) - ); + return ReactElementValidator.createFactory(tag); } - return ReactLegacyElement.markNonLegacyFactory( - ReactElement.createFactory(tag) - ); + return ReactElement.createFactory(tag); } /** @@ -7482,9 +7799,9 @@ var ReactDOM = mapObject({ module.exports = ReactDOM; -},{"./ReactElement":58,"./ReactElementValidator":59,"./ReactLegacyElement":67,"./mapObject":148}],44:[function(_dereq_,module,exports){ +},{"158":158,"63":63,"64":64}],47:[function(_dereq_,module,exports){ /** - * Copyright 2013-2014, Facebook, Inc. + * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the @@ -7494,18 +7811,16 @@ module.exports = ReactDOM; * @providesModule ReactDOMButton */ -"use strict"; +'use strict'; -var AutoFocusMixin = _dereq_("./AutoFocusMixin"); -var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); -var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); -var ReactElement = _dereq_("./ReactElement"); -var ReactDOM = _dereq_("./ReactDOM"); +var AutoFocusMixin = _dereq_(2); +var ReactBrowserComponentMixin = _dereq_(32); +var ReactClass = _dereq_(38); +var ReactElement = _dereq_(63); -var keyMirror = _dereq_("./keyMirror"); +var keyMirror = _dereq_(156); -// Store a reference to the