Compare commits

...

18 Commits

Author SHA1 Message Date
Sebastian McKenzie
7af4302d07 v5.1.11 2015-04-20 06:25:37 +01:00
Sebastian McKenzie
543770960c update 5.1.11 changelog 2015-04-20 06:24:30 +01:00
Sebastian McKenzie
a2975a72cc add 5.1.11 changelog 2015-04-20 06:23:53 +01:00
Sebastian McKenzie
beb3fd51d8 clean up CONTRIBUTING TOC 2015-04-20 06:16:33 +01:00
Sebastian McKenzie
9360860601 memoise and bind member expression decorators - fixes #1296 2015-04-20 06:16:20 +01:00
Sebastian McKenzie
7d4ecea8fb move react children coercion to opening element visitor - fixes #1276 2015-04-20 05:49:59 +01:00
Sebastian McKenzie
a44831b3fa Merge pull request #1285 from bucaran/contributing-doc-deps
Improve formatting and add rundown of deps with links
2015-04-20 00:24:30 +01:00
Sebastian McKenzie
8357f3900f Merge pull request #1282 from bcamper/vanilla-generator-runtime
Use vanilla regenerator when building runtime
2015-04-20 00:23:14 +01:00
Sebastian McKenzie
6b1c5bc358 remove interop require on bluebird - fixes #1289 2015-04-20 00:22:41 +01:00
Sebastian McKenzie
3564309a77 allow plugins to be specified as an object with transformer and position - fixes #1300 2015-04-20 00:05:06 +01:00
Sebastian McKenzie
c9518bb60d consider switches to be a valid scope - fixes #1297 2015-04-19 21:45:43 +01:00
Sebastian McKenzie
0f1215e33e add title to logging - fixes #1292 2015-04-19 16:06:58 +01:00
Sebastian McKenzie
d7b0b5bec0 add space to do-while code gen - fixes #1290 2015-04-17 17:35:36 -07:00
Jorge
3e5af404ab improve formatting and add rundown of deps with links 2015-04-17 15:15:03 +09:00
Sebastian McKenzie
1818094577 validate this before super on exit, not enter - fixes #1284 2015-04-16 22:04:18 -07:00
Brett Camper
6d712b3d14 use vanilla regenerator when building runtime
see #1015
2015-04-16 15:17:58 -04:00
Sebastian McKenzie
11389fe165 add 5.1.10 changelog 2015-04-15 16:12:56 -07:00
Sebastian McKenzie
0ee9531db3 5.1.10 2015-04-15 15:24:49 -07:00
32 changed files with 291 additions and 73 deletions

View File

@@ -13,6 +13,26 @@ _Note: Gaps between patch versions are faulty/broken releases._
See [CHANGELOG - 6to5](CHANGELOG-6to5.md) for the pre-4.0.0 version changelog.
## 5.1.11
* **Bug Fix**
* Memoise and bind member expression decorators.
* Move JSX children cleaning to opening element visitor. Fixes elements not being cleaned in certain scenarios.
* Consider `SwitchStatement`s to be `Scopable`.
* Fix `bluebirdCoroutines` calling `interopRequireWildcard` before it's defined.
* Add space to `do...while` code generation.
* Validate `super` use before `this` on `super` exit rather than entrance.
* **Polish**
* Add Babel name to logger.
## 5.1.10
* **Bug Fix**
* Remove `makePredicate` from acorn in favor of an `indexOf`.
* Remove statements to expression explosion when inserting a block statement.
* **Internal**
* Remove runtime compatibility check.
## 5.1.9
* **Bug Fix**

View File

@@ -1,9 +1,24 @@
<p align="center">
<strong><a href="#setup">Setup</a></strong>
|
<strong><a href="#running-tests">Running tests</a></strong>
|
<strong><a href="#workflow">Workflow</a></strong>
|
<strong><a href="#dependencies">Dependencies</a></strong>
|
<strong><a href="#code-standards">Code Standards</a></strong>
</p>
----
# Contributing
Contributions are always welcome, no matter how large or small. Before
contributing, please read the
[code of conduct](https://github.com/babel/babel/blob/master/CODE_OF_CONDUCT.md).
## Developing
#### Setup
@@ -21,7 +36,9 @@ $ make watch-core
```
This will compile Babel and then sit in the background and on file modification
recompile the necessary files.
recompile the necessary files. Babel itself is written in ES6. The source files
reside in `src/` and transpile to `lib/`
#### Running tests
@@ -44,6 +61,11 @@ Use mocha's `--grep` option to run a subset of tests by name:
$ mocha test/core/transformation.js --grep es7
```
If you don't have `mocha` installed globally, you can still use it from Babel's
dependencies in `node_modules`, but make sure `node_modules/.bin` is added to
your [`$PATH`](http://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path) environment variable.
#### Workflow
* Fork the repository
@@ -54,24 +76,91 @@ $ mocha test/core/transformation.js --grep es7
* Ensure the test are passing (`make test`)
* Create new pull request explaining your proposed change or reference an issue in your commit message
#### Dependencies
+ [ast-types](http://ghub.io/ast-types) This is required to monkeypatch regenerators AST definitions. Could be improved in the future.
+ [chalk](http://ghub.io/chalk) This is used for terminal color highlighting for syntax errors.
+ [convert-source-map](http://ghub.io/convert-source-map) Turns a source map object into a comment etc.
+ [core-js](http://ghub.io/core-js) Used for the polyfill.
+ [debug](http://ghub.io/debug) Used to output debugging information when NODE_DEBUG is set to babel.
+ [detect-indent](http://ghub.io/detect-indent) This is used in the code generator so it can infer indentation.
+ [estraverse](http://ghub.io/estraverse) The only method on this is attachComments. I'd like to implement our own comment attachment algorithm eventually though.
+ [esutils](http://ghub.io/esutils) Various ES related utilities. Check whether something is a keyword etc.
+ [fs-readdir-recursive](http://ghub.io/fs-readdir-recursive) Recursively search a directory for.
+ [globals](http://ghub.io/globals) A list of JavaScript global variables. This is used by the scope tracking to check for colliding variables.
+ [is-integer](http://ghub.io/is-integer) Checks if something is an integer.
+ [js-tokens](http://ghub.io/js-tokens) This is used to get tokens for syntax error highlighting.
+ [leven](http://ghub.io/leven) A levenstein algorithm to determine how close a word is to another. This is used to offer suggestions when using the utility.undeclaredVariableCheck transformer.
+ [line-numbers](http://ghub.io/line-numbers) Used to produce the code frames in syntax errors.
+ [lodash](http://ghub.io/lodash) Used for various utilities.
+ [minimatch](http://ghub.io/minimatch) This is used to match glob-style ignore/only filters.
+ [output-file-sync](http://ghub.io/output-file-sync) Synchronously writes a file and create its ancestor directories if needed.
+ [path-is-absolute](http://ghub.io/path-is-absolute) Checks if a path is absolute. C:\foo and \foo are considered absolute.
+ [regenerator](http://ghub.io/regenerator) This is used to transform generators/async functions.
+ [regexpu](http://ghub.io/regexpu) Used to transform unicode regex patterns.
+ [repeating](http://ghub.io/repeating) Repeats a string.
+ [shebang-regex](http://ghub.io/shebang-regex) Literally just a regex that matches shebangs.
+ [slash](http://ghub.io/slash) Normalises path separators.
+ [source-map](http://ghub.io/source-map) Generates sourcemaps.
+ [source-map-support](http://ghub.io/source-map-support) Adds source map support to babel-node/babel/register.
+ [strip-json-comments](http://ghub.io/strip-json-comments) Remove comments from a JSON string. This is used for .babelrc files.
+ [to-fast-properties](http://ghub.io/to-fast-properties) A V8 trick to put an object into fast properties mode.
+ [trim-right](http://ghub.io/trim-right) Trims the rightside whitespace.
+ [user-home](http://ghub.io/user-home) Gets the users home directory. This is used to resolve the babel-node/babel/register cache.
#### Code Standards
* **General**
* Max of five arguments for functions
* Max depth of four nested blocks
* 2-spaced soft tabs
* **Naming**
* CamelCase all class names
* camelBack all variable names
* **Spacing**
* Spaces after all keywords
* Spaces before all left curly braces
* **Comments**
* Use JSDoc-style comments for methods
* Single-line comments for ambiguous code
* **Quotes**
* Always use double quotes
* Only use single quotes when the string contains a double quote
* **Declaration**
* No unused variables
* No pollution of global variables and prototypes

View File

@@ -1,7 +1,7 @@
{
"name": "babel-core",
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "5.1.10",
"version": "5.1.11",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
"repository": "babel/babel",

View File

@@ -1,13 +1,13 @@
{
"name": "babel",
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "5.1.9",
"version": "5.1.10",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
"repository": "babel/babel",
"preferGlobal": true,
"dependencies": {
"babel-core": "^5.1.9",
"babel-core": "^5.1.10",
"chokidar": "^1.0.0",
"commander": "^2.6.0",
"fs-readdir-recursive": "^0.1.0",

View File

@@ -1,7 +1,7 @@
{
"name": "babel-runtime",
"description": "babel selfContained runtime",
"version": "5.1.9",
"version": "5.1.10",
"repository": "babel/babel",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"dependencies": {

View File

@@ -70,8 +70,8 @@ each(File.helpers, function (helperName) {
writeFile("helpers/" + helperName + ".js", buildHelper(helperName));
});
writeFile("regenerator/index.js", readFile("regenerator-babel/runtime-module", true));
writeFile("regenerator/runtime.js", selfContainify(readFile("regenerator-babel/runtime")));
writeFile("regenerator/index.js", readFile("regenerator/runtime-module", true));
writeFile("regenerator/runtime.js", selfContainify(readFile("regenerator/runtime")));
//

View File

@@ -71,7 +71,7 @@ export var ForInStatement = buildForXStatement("in");
export var ForOfStatement = buildForXStatement("of");
export function DoWhileStatement(node, print) {
this.keyword("do");
this.push("do ");
print(node.body);
this.space();
this.keyword("while");

View File

@@ -37,9 +37,9 @@ function checkNode(stack, node, scope) {
export default class File {
constructor(opts = {}) {
this.dynamicImportAbsoluteDefaults = [];
this.dynamicImportIds = {};
this.dynamicImports = [];
this.dynamicImportTypes = {};
this.dynamicImportIds = {};
this.dynamicImports = [];
this.usedHelpers = {};
this.dynamicData = {};
@@ -241,7 +241,10 @@ export default class File {
var plugin;
if (name) {
if (typeof name === "string") {
if (typeof name === "object" && name.transformer) {
plugin = name.transformer;
position ||= name.position;
} else if (typeof name === "string") {
// this is a plugin in the form of "foobar" or "foobar:after"
// where the optional colon is the delimiter for plugin position in the transformer stack
@@ -340,7 +343,7 @@ export default class File {
return source;
}
addImport(source: string, name?: string, absoluteDefault?: boolean): Object {
addImport(source: string, name?: string, type?: string): Object {
name ||= source;
var id = this.dynamicImportIds[name];
@@ -351,7 +354,11 @@ export default class File {
var specifiers = [t.importDefaultSpecifier(id)];
var declar = t.importDeclaration(specifiers, t.literal(source));
declar._blockHoist = 3;
if (absoluteDefault) this.dynamicImportAbsoluteDefaults.push(declar);
if (type) {
var modules = this.dynamicImportTypes[type] ||= [];
modules.push(declar);
}
if (this.transformers["es6.modules"].canTransform()) {
this.moduleFormatter.importSpecifier(specifiers[0], declar, this.dynamicImports);

View File

@@ -7,7 +7,7 @@ export default class Logger {
}
_buildMessage(msg: string): string {
var parts = this.filename;
var parts = `[BABEL] ${this.filename}`;
if (msg) parts += `: ${msg}`;
return parts;
}
@@ -18,7 +18,7 @@ export default class Logger {
deprecate(msg) {
if (!this.file.opts.suppressDeprecationMessages) {
console.error(msg);
console.error(this._buildMessage(msg));
}
}

View File

@@ -57,6 +57,8 @@ export default function (exports, opts) {
exports.JSXOpeningElement = {
exit(node, parent, scope, file) {
parent.children = react.buildChildren(parent);
var tagExpr = node.name;
var args = [];
@@ -144,10 +146,6 @@ export default function (exports, opts) {
};
exports.JSXElement = {
enter(node) {
node.children = react.buildChildren(node);
},
exit(node) {
var callExpr = node.openingElement;

View File

@@ -0,0 +1,33 @@
import * as t from "../../types";
export default function (decorators, scope) {
for (var i = 0; i < decorators.length; i++) {
var decorator = decorators[i];
var expression = decorator.expression;
if (!t.isMemberExpression(expression)) continue;
var temp = scope.generateMemoisedReference(expression.object);
var ref;
var nodes = [];
if (temp) {
ref = temp;
nodes.push(t.assignmentExpression("=", temp, expression.object));
} else {
ref = expression.object;
}
nodes.push(t.callExpression(
t.memberExpression(
t.memberExpression(ref, expression.property, expression.computed),
t.identifier("bind")
),
[ref]
));
decorator.expression = t.sequenceExpression(nodes);
}
return decorators;
}

View File

@@ -34,9 +34,8 @@ function cleanJSXElementLiteralChild(child, args) {
var lines = child.value.split(/\r\n|\n|\r/);
var lastNonEmptyLine = 0;
var i;
for (i = 0; i < lines.length; i++) {
for (let i = 0; i < lines.length; i++) {
if (lines[i].match(/[^ \t]/)) {
lastNonEmptyLine = i;
}
@@ -44,7 +43,7 @@ function cleanJSXElementLiteralChild(child, args) {
var str = "";
for (i = 0; i < lines.length; i++) {
for (let i = 0; i < lines.length; i++) {
var line = lines[i];
var isFirstLine = i === 0;

View File

@@ -124,6 +124,11 @@ export default class DefaultFormatter {
this.getLocalImports();
}
isModuleType(node, type) {
var modules = this.file.dynamicImportTypes[type];
return modules && modules.indexOf(node) >= 0;
}
transform() {
this.remapAssignments();
}

View File

@@ -80,7 +80,9 @@ export default class AMDFormatter extends DefaultFormatter {
this.defaultIds[key] = specifier.local;
}
if (includes(this.file.dynamicImportAbsoluteDefaults, node)) {
if (this.isModuleType(node, "absolute")) {
// absolute module reference
} else if (this.isModuleType(node, "absoluteDefault")) {
// prevent unnecessary renaming of dynamic imports
this.ids[node.source.value] = ref;
ref = t.memberExpression(ref, t.identifier("default"));

View File

@@ -45,7 +45,9 @@ export default class CommonJSFormatter extends DefaultFormatter {
// import foo from "foo";
if (t.isSpecifierDefault(specifier)) {
if (includes(this.file.dynamicImportAbsoluteDefaults, node)) {
if (this.isModuleType(node, "absolute")) {
// absolute module reference
} else if (this.isModuleType(node, "absoluteDefault")) {
this.internalRemap[variableName.name] = ref;
} else if (this.noInteropRequireImport) {
this.internalRemap[variableName.name] = t.memberExpression(ref, t.identifier("default"));
@@ -104,13 +106,16 @@ export default class CommonJSFormatter extends DefaultFormatter {
var call = t.callExpression(t.identifier("require"), [node.source]);
var uid;
if (includes(this.file.dynamicImportAbsoluteDefaults, node)) {
if (this.isModuleType(node, "absolute")) {
// absolute module reference
} else if (this.isModuleType(node, "absoluteDefault")) {
call = t.memberExpression(call, t.identifier("default"));
uid = node.specifiers[0].local;
} else {
uid = this.scope.generateUidBasedOnNode(node, "import");
}
uid ||= node.specifiers[0].local;
var declar = t.variableDeclaration("var", [
t.variableDeclarator(uid, call)
]);

View File

@@ -1,3 +1,4 @@
import memoiseDecorators from "../../helpers/memoise-decorators";
import ReplaceSupers from "../../helpers/replace-supers";
import * as nameMethod from "../../helpers/name-method";
import * as defineMap from "../../helpers/define-map";
@@ -50,7 +51,7 @@ var verifyConstructorVisitor = traverse.explode({
},
CallExpression: {
enter(node, parent, scope, state) {
exit(node, parent, scope, state) {
if (this.get("callee").isSuper()) {
state.hasBareSuper = true;
state.bareSuper = this;
@@ -292,6 +293,10 @@ class ClassTransformer {
var node = classBody[i];
var path = classBodyPaths[i];
if (node.decorators) {
memoiseDecorators(node.decorators, this.scope);
}
if (t.isMethodDefinition(node)) {
var isConstructor = node.kind === "constructor";
if (isConstructor) this.verifyConstructor(path);

View File

@@ -1,3 +1,4 @@
import memoiseDecorators from "../../helpers/memoise-decorators";
import * as defineMap from "../../helpers/define-map";
import * as t from "../../../types";
@@ -24,7 +25,9 @@ export function ObjectExpression(node, parent, scope, file) {
var mutatorMap = {};
for (var i = 0; i < node.properties.length; i++) {
defineMap.push(mutatorMap, node.properties[i], null, file);
var prop = node.properties[i];
if (prop.decorators) memoiseDecorators(prop.decorators, scope);
defineMap.push(mutatorMap, prop, null, file);
}
var obj = defineMap.toClassObject(mutatorMap);

View File

@@ -15,7 +15,7 @@ exports.Function = function (node, parent, scope, file) {
return remapAsyncToGenerator(
node,
t.memberExpression(file.addImport("bluebird"), t.identifier("coroutine")),
t.memberExpression(file.addImport("bluebird", null, "absolute"), t.identifier("coroutine")),
scope
);
};

View File

@@ -18,7 +18,7 @@ var astVisitor = traverse.explode({
// Symbol() -> _core.Symbol(); new Promise -> new _core.Promise
var modulePath = definitions.builtins[node.name];
return file.addImport(`${RUNTIME_MODULE_NAME}/core-js/${modulePath}`, node.name, true);
return file.addImport(`${RUNTIME_MODULE_NAME}/core-js/${modulePath}`, node.name, "absoluteDefault");
},
CallExpression(node, parent, scope, file) {
@@ -33,7 +33,7 @@ var astVisitor = traverse.explode({
var prop = callee.property;
if (!isSymbolIterator(prop)) return;
return t.callExpression(file.addImport(`${RUNTIME_MODULE_NAME}/core-js/get-iterator`, "getIterator", true), [callee.object]);
return t.callExpression(file.addImport(`${RUNTIME_MODULE_NAME}/core-js/get-iterator`, "getIterator", "absoluteDefault"), [callee.object]);
},
BinaryExpression(node, parent, scope, file) {
@@ -45,7 +45,7 @@ var astVisitor = traverse.explode({
if (!isSymbolIterator(left)) return;
return t.callExpression(
file.addImport(`${RUNTIME_MODULE_NAME}/core-js/is-iterable`, "isIterable", true),
file.addImport(`${RUNTIME_MODULE_NAME}/core-js/is-iterable`, "isIterable", "absoluteDefault"),
[node.right]
);
},
@@ -71,7 +71,7 @@ var astVisitor = traverse.explode({
if (scope.getBindingIdentifier(obj.name)) return;
var modulePath = methods[prop.name];
return file.addImport(`${RUNTIME_MODULE_NAME}/core-js/${modulePath}`, `${obj.name}$${prop.name}`, true);
return file.addImport(`${RUNTIME_MODULE_NAME}/core-js/${modulePath}`, `${obj.name}$${prop.name}`, "absoluteDefault");
},
exit(node, parent, scope, file) {
@@ -85,7 +85,7 @@ var astVisitor = traverse.explode({
var modulePath = definitions.builtins[obj.name];
return t.memberExpression(
file.addImport(`${RUNTIME_MODULE_NAME}/core-js/${modulePath}`, `${obj.name}`, true),
file.addImport(`${RUNTIME_MODULE_NAME}/core-js/${modulePath}`, `${obj.name}`, "absoluteDefault"),
prop
);
}
@@ -102,11 +102,11 @@ exports.Program = function (node, parent, scope, file) {
exports.pre = function (file) {
file.set("helperGenerator", function (name) {
return file.addImport(`${RUNTIME_MODULE_NAME}/helpers/${name}`, name, true);
return file.addImport(`${RUNTIME_MODULE_NAME}/helpers/${name}`, name, "absoluteDefault");
});
file.setDynamic("regeneratorIdentifier", function () {
return file.addImport(`${RUNTIME_MODULE_NAME}/regenerator`, "regeneratorRuntime", true);
return file.addImport(`${RUNTIME_MODULE_NAME}/regenerator`, "regeneratorRuntime", "absoluteDefault");
});
};

View File

@@ -6,7 +6,7 @@
"DoWhileStatement": ["Statement", "Loop", "While", "Scopable"],
"IfStatement": ["Statement"],
"ReturnStatement": ["Statement"],
"SwitchStatement": ["Statement"],
"SwitchStatement": ["Statement", "Scopable"],
"ThrowStatement": ["Statement"],
"TryStatement": ["Statement"],
"WhileStatement": ["Statement", "Loop", "While", "Scopable"],

View File

@@ -1,8 +1,6 @@
"use strict";
var _bluebird2 = require("bluebird");
var _bluebird3 = babelHelpers.interopRequireWildcard(_bluebird2);
var _bluebird = require("bluebird");
var Foo = (function () {
function Foo() {
@@ -11,7 +9,7 @@ var Foo = (function () {
babelHelpers.createClass(Foo, [{
key: "foo",
value: _bluebird3["default"].coroutine(function* () {
value: _bluebird.coroutine(function* () {
var wat = yield bar();
})
}]);

View File

@@ -1,11 +1,7 @@
"use strict";
var _bluebird2 = require("bluebird");
var _bluebird = require("bluebird");
var _bluebird3 = _interopRequireWildcard(_bluebird2);
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; };
var foo = _bluebird3["default"].coroutine(function* () {
var foo = _bluebird.coroutine(function* () {
var wat = yield bar();
});

View File

@@ -1,14 +1,10 @@
"use strict";
var _bluebird2 = require("bluebird");
var _bluebird3 = _interopRequireWildcard(_bluebird2);
var _bluebird = require("bluebird");
var _bar;
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; };
var foo = _bar = _bluebird3["default"].coroutine(function* () {
var foo = _bar = _bluebird.coroutine(function* () {
console.log(_bar);
});

View File

@@ -1,11 +1,7 @@
"use strict";
var _bluebird2 = require("bluebird");
var _bluebird = require("bluebird");
var _bluebird3 = _interopRequireWildcard(_bluebird2);
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; };
var foo = _bluebird3["default"].coroutine(function* () {
var foo = _bluebird.coroutine(function* () {
var wat = yield bar();
});

View File

@@ -0,0 +1,11 @@
let a = true;
let b = false;
switch (a) {
case true:
let b = 2;
break;
case false:
let c = 3;
break;
}

View File

@@ -0,0 +1,13 @@
"use strict";
var a = true;
var b = false;
switch (a) {
case true:
var b = 2;
break;
case false:
var c = 3;
break;
}

View File

@@ -0,0 +1,5 @@
class Foo extends Bar {
constructor() {
super(this);
}
}

View File

@@ -0,0 +1,3 @@
{
"throws": "'this' is not allowed before super()"
}

View File

@@ -1,13 +0,0 @@
"use strict";
var Foo = (function (_Bar) {
function Foo() {
babelHelpers.classCallCheck(this, Foo);
this.foo = "bar";
babelHelpers.get(Object.getPrototypeOf(Foo.prototype), "constructor", this).call(this);
}
babelHelpers.inherits(Foo, _Bar);
return Foo;
})(Bar);

View File

@@ -0,0 +1,18 @@
var foo = {
bar: function () { assert.equal(this, foo); },
foobar: {
bar: function () { assert.equal(this, foo.foobar); },
}
};
(class {
@foo.bar
@foo.foobar.bar
bar() {}
});
({
@foo.bar
@foo.foobar.bar
bar() {}
});

View File

@@ -0,0 +1,11 @@
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
React.render(<HelloMessage name={
<span>
Sebastian
</span>
} />, mountNode);

View File

@@ -0,0 +1,18 @@
var HelloMessage = React.createClass({
displayName: "HelloMessage",
render: function render() {
return React.createElement(
"div",
null,
"Hello ",
this.props.name
);
}
});
React.render(React.createElement(HelloMessage, { name: React.createElement(
"span",
null,
"Sebastian"
) }), mountNode);