From fbe1de77ec1ce5977f8309ecedf29009dc4d283c Mon Sep 17 00:00:00 2001
From: Chris Marisic
Date: Wed, 27 Aug 2014 11:32:37 -0400
Subject: [PATCH 001/859] Fix 404
Fix typo in MsBuild hyperlink that results in a 404
---
site/jekyll/guides/es6.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/site/jekyll/guides/es6.md b/site/jekyll/guides/es6.md
index f3fc4d366..fa3911823 100644
--- a/site/jekyll/guides/es6.md
+++ b/site/jekyll/guides/es6.md
@@ -63,7 +63,7 @@ ReactSiteConfiguration.Configuration
.SetUseHarmony(true)
.AddScript("~/Content/Sample.jsx");
```
-If you are using [MSBuild to precompile your JSX](/guide/msbuild.html), you also need to enable it in MSBuild via the `UseHarmony="true"` flag in your build script (`TransformJsx.proj` by default):
+If you are using [MSBuild to precompile your JSX](/guides/msbuild.html), you also need to enable it in MSBuild via the `UseHarmony="true"` flag in your build script (`TransformJsx.proj` by default):
```xml
From 60cba9096151df31c21bf06032597a7a5b560cce Mon Sep 17 00:00:00 2001
From: Daniel Lo Nigro
Date: Sun, 14 Sep 2014 18:07:05 -0700
Subject: [PATCH 002/859] Allow namespaced components to be rendered
server-side. Closes #37
---
src/React.Tests/Core/ReactComponentTest.cs | 26 +++++++++++++++--
src/React/ReactComponent.cs | 33 +++++++++++++++++++++-
2 files changed, 55 insertions(+), 4 deletions(-)
diff --git a/src/React.Tests/Core/ReactComponentTest.cs b/src/React.Tests/Core/ReactComponentTest.cs
index 72d48130f..afe6a47de 100644
--- a/src/React.Tests/Core/ReactComponentTest.cs
+++ b/src/React.Tests/Core/ReactComponentTest.cs
@@ -20,7 +20,7 @@ public class ReactComponentTest
public void RenderHtmlShouldThrowExceptionIfComponentDoesNotExist()
{
var environment = new Mock();
- environment.Setup(x => x.HasVariable("Foo")).Returns(false);
+ environment.Setup(x => x.Execute("typeof Foo !== 'undefined'")).Returns(false);
var component = new ReactComponent(environment.Object, "Foo", "container");
Assert.Throws(() =>
@@ -33,7 +33,7 @@ public void RenderHtmlShouldThrowExceptionIfComponentDoesNotExist()
public void RenderHtmlShouldCallRenderComponent()
{
var environment = new Mock();
- environment.Setup(x => x.HasVariable("Foo")).Returns(true);
+ environment.Setup(x => x.Execute("typeof Foo !== 'undefined'")).Returns(true);
var component = new ReactComponent(environment.Object, "Foo", "container")
{
@@ -48,7 +48,7 @@ public void RenderHtmlShouldCallRenderComponent()
public void RenderHtmlShouldWrapComponentInDiv()
{
var environment = new Mock();
- environment.Setup(x => x.HasVariable("Foo")).Returns(true);
+ environment.Setup(x => x.Execute("typeof Foo !== 'undefined'")).Returns(true);
environment.Setup(x => x.Execute(@"React.renderComponentToString(Foo({""hello"":""World""}))"))
.Returns("[HTML]");
@@ -77,5 +77,25 @@ public void RenderJavaScriptShouldCallRenderComponent()
result
);
}
+
+ [TestCase("Foo", true)]
+ [TestCase("Foo.Bar", true)]
+ [TestCase("Foo.Bar.Baz", true)]
+ [TestCase("alert()", false)]
+ [TestCase("Foo.alert()", false)]
+ [TestCase("lol what", false)]
+ public void TestEnsureComponentNameValid(string input, bool expected)
+ {
+ var isValid = true;
+ try
+ {
+ ReactComponent.EnsureComponentNameValid(input);
+ }
+ catch (ReactInvalidComponentException)
+ {
+ isValid = false;
+ }
+ Assert.AreEqual(expected, isValid);
+ }
}
}
diff --git a/src/React/ReactComponent.cs b/src/React/ReactComponent.cs
index cbafaf959..24371467a 100644
--- a/src/React/ReactComponent.cs
+++ b/src/React/ReactComponent.cs
@@ -7,6 +7,8 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
+using System.Linq;
+using System.Text.RegularExpressions;
using Newtonsoft.Json;
using React.Exceptions;
@@ -17,6 +19,13 @@ namespace React
///
public class ReactComponent : IReactComponent
{
+ ///
+ /// Regular expression used to validate JavaScript identifiers. Used to ensure component
+ /// names are valid.
+ /// Based off https://gist.github.com/Daniel15/3074365
+ ///
+ private static readonly Regex _identifierRegex = new Regex(@"^[a-zA-Z_$][0-9a-zA-Z_$]*(?:\[(?:"".+""|\'.+\'|\d+)\])*?$", RegexOptions.Compiled);
+
///
/// Environment this component has been created in
///
@@ -45,6 +54,7 @@ public class ReactComponent : IReactComponent
/// The ID of the container DIV for this component
public ReactComponent(IReactEnvironment environment, string componentName, string containerId)
{
+ EnsureComponentNameValid(componentName);
_environment = environment;
_componentName = componentName;
_containerId = containerId;
@@ -89,7 +99,12 @@ public string RenderJavaScript()
///
private void EnsureComponentExists()
{
- if (!_environment.HasVariable(_componentName))
+ // This is safe as componentName was validated via EnsureComponentNameValid()
+ var componentExists = _environment.Execute(string.Format(
+ "typeof {0} !== 'undefined'",
+ _componentName
+ ));
+ if (!componentExists)
{
throw new ReactInvalidComponentException(string.Format(
"Could not find a component named '{0}'. Did you forget to add it to " +
@@ -112,5 +127,21 @@ private string GetComponentInitialiser()
encodedProps
);
}
+
+ ///
+ /// Validates that the specified component name is valid
+ ///
+ ///
+ internal static void EnsureComponentNameValid(string componentName)
+ {
+ var isValid = componentName.Split('.').All(segment => _identifierRegex.IsMatch(segment));
+ if (!isValid)
+ {
+ throw new ReactInvalidComponentException(string.Format(
+ "Invalid component name '{0}'",
+ componentName
+ ));
+ }
+ }
}
}
From f13c0e5dfdef25980fadeaf8c0e0fc7fcf36d985 Mon Sep 17 00:00:00 2001
From: Daniel Lo Nigro
Date: Sun, 14 Sep 2014 18:45:24 -0700
Subject: [PATCH 003/859] Include more detail in error messages. Closes #17
---
.../Exceptions/ReactScriptLoadException.cs | 41 +++++++++
.../ReactServerRenderingException.cs | 41 +++++++++
src/React/IReactEnvironment.cs | 9 ++
src/React/JsxTransformer.cs | 14 ++-
src/React/React.csproj | 2 +
src/React/ReactComponent.cs | 31 +++++--
src/React/ReactEnvironment.cs | 88 +++++++++++++++++--
src/React/Resources/shims.js | 6 +-
8 files changed, 215 insertions(+), 17 deletions(-)
create mode 100644 src/React/Exceptions/ReactScriptLoadException.cs
create mode 100644 src/React/Exceptions/ReactServerRenderingException.cs
diff --git a/src/React/Exceptions/ReactScriptLoadException.cs b/src/React/Exceptions/ReactScriptLoadException.cs
new file mode 100644
index 000000000..733939c63
--- /dev/null
+++ b/src/React/Exceptions/ReactScriptLoadException.cs
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+using System;
+using System.Runtime.Serialization;
+
+namespace React.Exceptions
+{
+ ///
+ /// Thrown when an error is encountered while loading a JavaScript file.
+ ///
+ [Serializable]
+ public class ReactScriptLoadException : ReactException
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The message that describes the error.
+ public ReactScriptLoadException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The error message that explains the reason for the exception.
+ /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.
+ public ReactScriptLoadException(string message, Exception innerException)
+ : base(message, innerException) { }
+
+ ///
+ /// Used by deserialization
+ ///
+ protected ReactScriptLoadException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+ }
+}
diff --git a/src/React/Exceptions/ReactServerRenderingException.cs b/src/React/Exceptions/ReactServerRenderingException.cs
new file mode 100644
index 000000000..d07ab4a29
--- /dev/null
+++ b/src/React/Exceptions/ReactServerRenderingException.cs
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+using System;
+using System.Runtime.Serialization;
+
+namespace React.Exceptions
+{
+ ///
+ /// Thrown when an error occurs during server rendering of a React component.
+ ///
+ [Serializable]
+ public class ReactServerRenderingException : ReactException
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The message that describes the error.
+ public ReactServerRenderingException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The error message that explains the reason for the exception.
+ /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.
+ public ReactServerRenderingException(string message, Exception innerException)
+ : base(message, innerException) { }
+
+ ///
+ /// Used by deserialization
+ ///
+ protected ReactServerRenderingException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+ }
+}
diff --git a/src/React/IReactEnvironment.cs b/src/React/IReactEnvironment.cs
index 9fa518cd3..b14f8b2ff 100644
--- a/src/React/IReactEnvironment.cs
+++ b/src/React/IReactEnvironment.cs
@@ -41,6 +41,15 @@ public interface IReactEnvironment
/// Result of the JavaScript code
T Execute(string code);
+ ///
+ /// Executes the provided JavaScript function, returning a result of the specified type.
+ ///
+ /// Type to return
+ /// JavaScript function to execute
+ /// Arguments to pass to function
+ /// Result of the JavaScript code
+ T Execute(string function, params object[] args);
+
///
/// Attempts to execute the provided JavaScript code using the current engine. If an
/// exception is thrown, retries the execution using a new thread (and hence a new engine)
diff --git a/src/React/JsxTransformer.cs b/src/React/JsxTransformer.cs
index 696f91f58..bd0e4bc52 100644
--- a/src/React/JsxTransformer.cs
+++ b/src/React/JsxTransformer.cs
@@ -98,7 +98,19 @@ public string TransformJsxFile(string filename, bool? useHarmony = null)
}
// 3. Not cached, perform the transformation
- return TransformJsxWithHeader(contents, hash, useHarmony);
+ try
+ {
+ return TransformJsxWithHeader(contents, hash, useHarmony);
+ }
+ catch (JsxException ex)
+ {
+ // Add the filename to the error message
+ throw new JsxException(string.Format(
+ "In file \"{0}\": {1}",
+ filename,
+ ex.Message
+ ));
+ }
}
);
}
diff --git a/src/React/React.csproj b/src/React/React.csproj
index cae539eac..8aadeb367 100644
--- a/src/React/React.csproj
+++ b/src/React/React.csproj
@@ -83,6 +83,8 @@
Properties\SharedAssemblyVersionInfo.cs
+
+
diff --git a/src/React/ReactComponent.cs b/src/React/ReactComponent.cs
index 24371467a..4defe1302 100644
--- a/src/React/ReactComponent.cs
+++ b/src/React/ReactComponent.cs
@@ -9,6 +9,7 @@
using System.Linq;
using System.Text.RegularExpressions;
+using JavaScriptEngineSwitcher.Core;
using Newtonsoft.Json;
using React.Exceptions;
@@ -68,15 +69,27 @@ public ReactComponent(IReactEnvironment environment, string componentName, strin
public string RenderHtml()
{
EnsureComponentExists();
- var html = _environment.Execute(
- string.Format("React.renderComponentToString({0})", GetComponentInitialiser())
- );
- // TODO: Allow changing of the wrapper tag element from a DIV to something else
- return string.Format(
- "
{1}
",
- _containerId,
- html
- );
+ try
+ {
+ var html = _environment.Execute(
+ string.Format("React.renderComponentToString({0})", GetComponentInitialiser())
+ );
+ // TODO: Allow changing of the wrapper tag element from a DIV to something else
+ return string.Format(
+ "
{1}
",
+ _containerId,
+ html
+ );
+ }
+ catch (JsRuntimeException ex)
+ {
+ throw new ReactServerRenderingException(string.Format(
+ "Error while rendering \"{0}\" to \"{2}\": {1}",
+ _componentName,
+ ex.Message,
+ _containerId
+ ));
+ }
}
///
diff --git a/src/React/ReactEnvironment.cs b/src/React/ReactEnvironment.cs
index 14f46b27d..9a30b86a0 100644
--- a/src/React/ReactEnvironment.cs
+++ b/src/React/ReactEnvironment.cs
@@ -14,6 +14,7 @@
using System.Text;
using System.Threading;
using JavaScriptEngineSwitcher.Core;
+using React.Exceptions;
namespace React
{
@@ -169,7 +170,18 @@ private void EnsureUserScriptsLoaded()
foreach (var file in _config.Scripts)
{
var contents = JsxTransformer.TransformJsxFile(file);
- Execute(contents);
+ try
+ {
+ Execute(contents);
+ }
+ catch (JsRuntimeException ex)
+ {
+ throw new ReactScriptLoadException(string.Format(
+ "Error while loading \"{0}\": {1}",
+ file,
+ ex.Message
+ ));
+ }
}
Engine.SetVariableValue(USER_SCRIPTS_LOADED_KEY, true);
}
@@ -180,7 +192,14 @@ private void EnsureUserScriptsLoaded()
/// JavaScript to execute
public void Execute(string code)
{
- Engine.Execute(code);
+ try
+ {
+ Engine.Execute(code);
+ }
+ catch (JsRuntimeException ex)
+ {
+ throw WrapJavaScriptRuntimeException(ex);
+ }
}
///
@@ -191,7 +210,33 @@ public void Execute(string code)
/// Result of the JavaScript code
public T Execute(string code)
{
- return Engine.Evaluate(code);
+ try
+ {
+ return Engine.Evaluate(code);
+ }
+ catch (JsRuntimeException ex)
+ {
+ throw WrapJavaScriptRuntimeException(ex);
+ }
+ }
+
+ ///
+ /// Executes the provided JavaScript function, returning a result of the specified type.
+ ///
+ /// Type to return
+ /// JavaScript function to execute
+ /// Arguments to pass to function
+ /// Result of the JavaScript code
+ public T Execute(string function, params object[] args)
+ {
+ try
+ {
+ return Engine.CallFunction(function, args);
+ }
+ catch (JsRuntimeException ex)
+ {
+ throw WrapJavaScriptRuntimeException(ex);
+ }
}
///
@@ -201,7 +246,14 @@ public T Execute(string code)
/// true if the variable exists; false otherwise
public bool HasVariable(string name)
{
- return Engine.HasVariable(name);
+ try
+ {
+ return Engine.HasVariable(name);
+ }
+ catch (JsRuntimeException ex)
+ {
+ throw WrapJavaScriptRuntimeException(ex);
+ }
}
///
@@ -278,7 +330,7 @@ public T ExecuteWithLargerStackIfRequired(string function, params object[] ar
{
try
{
- return Engine.CallFunction(function, args);
+ return Execute(function, args);
}
catch (Exception)
{
@@ -292,7 +344,7 @@ public T ExecuteWithLargerStackIfRequired(string function, params object[] ar
try
{
// New engine will be created here (as this is a new thread)
- result = Engine.CallFunction(function, args);
+ result = Execute(function, args);
}
catch (Exception threadEx)
{
@@ -336,5 +388,29 @@ public void Dispose()
{
_engineFactory.DisposeEngineForCurrentThread();
}
+
+ ///
+ /// Updates the Message of a to be more useful, containing
+ /// the line and column numbers.
+ ///
+ /// Original exception
+ /// New exception
+ private JsRuntimeException WrapJavaScriptRuntimeException(JsRuntimeException ex)
+ {
+ return new JsRuntimeException(string.Format(
+ "{0}\r\nLine: {1}\r\nColumn:{2}",
+ ex.Message,
+ ex.LineNumber,
+ ex.ColumnNumber
+ ), ex.EngineName, ex.EngineVersion)
+ {
+ ErrorCode = ex.ErrorCode,
+ Category = ex.Category,
+ LineNumber = ex.LineNumber,
+ ColumnNumber = ex.ColumnNumber,
+ SourceFragment = ex.SourceFragment,
+ Source = ex.Source,
+ };
+ }
}
}
diff --git a/src/React/Resources/shims.js b/src/React/Resources/shims.js
index 96c60ca56..568a7691e 100644
--- a/src/React/Resources/shims.js
+++ b/src/React/Resources/shims.js
@@ -20,5 +20,9 @@ if (!Object.freeze) {
}
function ReactNET_transform(input, harmony) {
- return global.JSXTransformer.transform(input, { harmony: !!harmony }).code;
+ try {
+ return global.JSXTransformer.transform(input, { harmony: !!harmony }).code;
+ } catch (ex) {
+ throw new Error(ex.message + " (at line " + ex.lineNumber + " column " + ex.column + ")");
+ }
}
\ No newline at end of file
From 4f20c5d49032992897a1309888e887ef95a08a29 Mon Sep 17 00:00:00 2001
From: Daniel Lo Nigro
Date: Sun, 14 Sep 2014 18:46:20 -0700
Subject: [PATCH 004/859] Bump version number to 1.1.2
---
build.proj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/build.proj b/build.proj
index a175ac947..50e822baa 100644
--- a/build.proj
+++ b/build.proj
@@ -11,7 +11,7 @@ of patent rights can be found in the PATENTS file in the same directory.
11
- 1
+ 20http://reactjs.net/packages/$(MSBuildProjectDirectory)\tools\MSBuildTasks
From 9da55540fe9a40f2e6d6f9e54cced41d4b90df57 Mon Sep 17 00:00:00 2001
From: Daniel Lo Nigro
Date: Sun, 14 Sep 2014 19:00:12 -0700
Subject: [PATCH 005/859] Blog post for 1.1.2 release
---
site/jekyll/_posts/2014-09-14-1.1.2-release.md | 15 +++++++++++++++
1 file changed, 15 insertions(+)
create mode 100644 site/jekyll/_posts/2014-09-14-1.1.2-release.md
diff --git a/site/jekyll/_posts/2014-09-14-1.1.2-release.md b/site/jekyll/_posts/2014-09-14-1.1.2-release.md
new file mode 100644
index 000000000..f19dde050
--- /dev/null
+++ b/site/jekyll/_posts/2014-09-14-1.1.2-release.md
@@ -0,0 +1,15 @@
+---
+title: "ReactJS.NET 1.1.2 - Better errors messages and namespaced JSX"
+layout: post
+author: Daniel Lo Nigro
+---
+
+I'm happy to announce the release of ReactJS.NET 1.1.2! This is a minor release and includes a number of changes and fixes since version 1.1.1:
+
+ * Error messages now contain more details, including file name, component name, line number and column number. This should make debugging a bit easier, especially if you're debugging without Visual Studio attached. ([#17](https://github.com/reactjs/React.NET/issues/17))
+ * [JSX Namespacing](http://facebook.github.io/react/blog/2014/07/17/react-v0.11.html#jsx-namespacing) is now supported ([#37](https://github.com/reactjs/React.NET/issues/37))
+
+Have fun, and as always, please feel free to send feedback or bug reports
+[on GitHub](https://github.com/reactjs/React.NET).
+
+— Daniel
From 6525710a405d1328220a9e07652e6031a8e6e180 Mon Sep 17 00:00:00 2001
From: Daniel Lo Nigro
Date: Sun, 14 Sep 2014 19:01:04 -0700
Subject: [PATCH 006/859] Bump version number for dev
---
build.proj | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/build.proj b/build.proj
index 50e822baa..b538364f7 100644
--- a/build.proj
+++ b/build.proj
@@ -11,7 +11,7 @@ of patent rights can be found in the PATENTS file in the same directory.
11
- 2
+ 30http://reactjs.net/packages/$(MSBuildProjectDirectory)\tools\MSBuildTasks
@@ -30,7 +30,7 @@ of patent rights can be found in the PATENTS file in the same directory.
-
@@ -88,7 +88,7 @@ of patent rights can be found in the PATENTS file in the same directory.
-
+
-
\ No newline at end of file
+
From ec1316409083c55ea98f79d97a78300719048be6 Mon Sep 17 00:00:00 2001
From: Daniel Lo Nigro
Date: Sun, 14 Sep 2014 19:05:55 -0700
Subject: [PATCH 007/859] Include date in post on home page
---
site/jekyll/index.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/site/jekyll/index.md b/site/jekyll/index.md
index 7cf1ff96b..d937e839a 100644
--- a/site/jekyll/index.md
+++ b/site/jekyll/index.md
@@ -27,6 +27,7 @@ id: home
Latest news:
{{ site.posts.first.title }}
+ ({{ site.posts.first.date | date: "%B %e, %Y" }})
From 74be3368ac57fecb5868ff6dcbb3fc58ab23ce4f Mon Sep 17 00:00:00 2001
From: Daniel Lo Nigro
Date: Fri, 31 Oct 2014 22:22:56 -0700
Subject: [PATCH 008/859] Upgrade React to 0.12.0
---
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 +-
.../Views/Home/Index.cshtml | 2 +-
src/React.Sample.Mvc4/Views/Home/Index.cshtml | 2 +-
src/React/Resources/JSXTransformer.js | 2336 +++---
src/React/Resources/react-with-addons.js | 6600 ++++++++---------
8 files changed, 4459 insertions(+), 4497 deletions(-)
diff --git a/site/jekyll/getting-started/tutorial.md b/site/jekyll/getting-started/tutorial.md
index 749a277c3..1a4333929 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:
-
+