Xaml Script is an experiment in binding JavaScript to Xaml, using function/reactive programming techniques (insipred by ReactNative)
Note: At this point contributions aren't supported
Note: Today there are a lot of hand authored components that have tight coupling (classhandlers.tt, xsrt.tsc, etc.) which need significant refactoring. The initial prototyping work has worked reasonably, but we need to revisit the approach
This project uses a git submodule
reference to https://github.com/codemonkeychris/jsrt
git clone https://github.com/codemonkeychris/xs.git
cd xs
git submodule init
git submodule update
- Install Windows 10 RTM build
- Install Visual Studio 2015 RTM - https://www.visualstudio.com/products/visual-studio-2015-downloads-vs
- Install TypeScript - required to
F5
in VS, as there is a custom build step that invokes TSC
npm install -g typescript@next
This is a basic Chakra host, currently with as little policy as possible. The ValueMarshaller infrastructure is probably the most out there thing, but it needs to be integrated with the host.
This is the logic for the bulk of the XS project. Currently written in C# for expediency, but should be migrated to C++ to avoid the second GC in the process.
Simple test host, ideally this should be replaced by a Yomen generator or something, this is really just file->new project.
Unit test project. Running this will produce a display that shows pass/fail status for each tests.
Tests are defined in manualtests\jsx\tests.js
.
F5
from Visual Studio 2015 should work.
The default program will be created in (PS syntax)
C:\Users\$env:username\AppData\Local\Packages\XSTest_8z7hbd2ww68bp\RoamingState\xs-program.js
When the program is running, you can edit the JavaScript file
The recommended usage is to integrate using JSX syntax. The hacky React namespace provided handles
eventHandlers and creates the right object shape. JSX provides a nice XML syntax over object
construction - basically the <Xaml.StackPanel>
instead of React.createElement(Xaml.StackPanel)
My recommended steps to edit using JSX is:
- Edit
src\watch.ps1
to point to your user directory
Note:
watch.ps1
only accepts relative paths because of limitations of TSC the node.js TSC compilter.
-
Enable powershell scripts - easiest way is to run
set-executionpolicy unrestricted
from an admin powershell window -
Run
watch.ps1
from thesrc
directory -
Edit
src\xstest\jsx\app.js
from the XSTest, when you save the program will update
The system works by hosting the JavaScript engine in a Xaml based Universal Windows App (UWA). When the file is changed, the app restarts, preserving the state of the app.
The structure of the program is:
var App;
(function (App) {
App.setInitialState = function() {
host.setState({ x1: "Click Me!" });
};
App.eventHandlers = {
$1: function() {
host.setState({ x1: "Clicked!" });
}
};
App.render = function() {
return {
type:'StackPanel',
name: 'root',
children: [
{
type:'TextBlock',
name: 'header',
text:'Welcome to XS!',
fontSize:56,
margin:"30,10,10,10"
},
{
type: 'Button',
name:'b1',
onClick: '$1',
content: {
type:'TextBlock',
name:'t1',
text: 'O:' + host.getState().x1
}
}
]
};
}
})(App || (App = {}));
At the moment, all the names are hard coded. Still TBD how this design lands, but this documents how it works today.
This sample, converted to JSX is a bit nicer because the event handlers are dealt with automatically.
var App;
(function (App) {
App.setInitialState = function() {
host.setState({ x1: "Click Me!" });
};
function clicked() {
host.setState({ x1: "Clicked!" });
}
App.render = function() {
return (
<Xaml.StackPanel name='root'>
<Xaml.TextBlock name='header'
text='Welcome to XS!'
fontSize='56'
margin='30,10,10,10' />
<Xaml.Button name='b1'
content={<Xaml.TextBlock
name='t1'
text={'O:' + host.getState().x1 } />
} />
</Xaml.StackPanel>
);
}
})(App || (App = {}));
In this function you should make calls to host.setState
to populate the default
value for state. This will be reset only when the application is restarted.
This will eventually go away, for now, you need to have names that match your functions
from the render
method. Typically you end up calling host.setState
in event
handlers to update the app.
This is the work horse of your program. You create a JSON block that defines the UI.
Different (for now) than React, this is a pure data block, no function are allowed, etc.
Each node has a type
member which is an abreviated WinRT type name, and then the
set of members that we have implemented the parsing for.
The system is smart and diffs the JSON between calls to render and performs the minimal updates to the Xaml tree.
This assigns new values to the global state object (using ES6 assign semantics) and returns the global state object. The state is preserved across program changes, but not currently serialized across process restarts.
The set of controls, properties, and events available to the declaration of your view are determined by the hand coded content in ClassHandlers.tt
ClassHandlers.cs is an output file that is generated by VS' T4T compilation of ClassHandlers.tt