-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 68e11a8
Showing
28 changed files
with
3,595 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Auto detect text files and perform LF normalization | ||
*.js text=on | ||
*.js eol=lf | ||
|
||
# Custom for Visual Studio | ||
*.cs diff=csharp | ||
*.sln merge=union | ||
*.csproj merge=union | ||
*.vbproj merge=union | ||
*.fsproj merge=union | ||
*.dbproj merge=union | ||
|
||
# Standard to msysgit | ||
*.doc diff=astextplain | ||
*.DOC diff=astextplain | ||
*.docx diff=astextplain | ||
*.DOCX diff=astextplain | ||
*.dot diff=astextplain | ||
*.DOT diff=astextplain | ||
*.pdf diff=astextplain | ||
*.PDF diff=astextplain | ||
*.rtf diff=astextplain | ||
*.RTF diff=astextplain |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
node_modules/ | ||
bower_components/ | ||
docs/docker/ | ||
tools/ | ||
.svn | ||
.git | ||
npm-debug.log | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
bower_components/ | ||
docs/docker/ | ||
lib/ | ||
node_modules/ | ||
src/ | ||
tests/ | ||
tools/ | ||
Gruntfile.js | ||
.svn | ||
.git | ||
npm-debug.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/** Gruntfile for [jsser.js](http://github.com/LeonardoVal/jsser.js). | ||
*/ | ||
var sourceFiles = [ 'src/__prologue__.js', | ||
'src/registry.js', | ||
'src/serialization.js', | ||
'src/materialization.js', | ||
'src/constructions.js', | ||
'src/wrapup.js', | ||
// end | ||
'src/__epilogue__.js']; | ||
|
||
// Init config. //////////////////////////////////////////////////////////////// | ||
module.exports = function(grunt) { | ||
grunt.file.defaultEncoding = 'utf8'; | ||
// Init config. //////////////////////////////////////////////////////////////// | ||
grunt.initConfig({ | ||
pkg: grunt.file.readJSON('package.json'), | ||
jison: { /////////////////////////////////////////////////////////////////////////////////// | ||
build: { | ||
options: { | ||
type: 'slr', | ||
moduleType: 'js' | ||
}, | ||
files: { | ||
'src/parser.js': 'src/parser.jison' | ||
} | ||
} | ||
}, | ||
concat_sourcemap: { //////////////////////////////////////////////////////////////////////// | ||
build: { | ||
src: sourceFiles, | ||
dest: 'build/<%= pkg.name %>.js', | ||
options: { | ||
separator: '\n\n' | ||
} | ||
}, | ||
}, | ||
uglify: { ////////////////////////////////////////////////////////////////////////////////// | ||
build: { | ||
src: 'build/<%= pkg.name %>.js', | ||
dest: 'build/<%= pkg.name %>.min.js', | ||
options: { | ||
banner: '//! <%= pkg.name %> <%= pkg.version %>\n', | ||
report: 'min', | ||
sourceMap: true, | ||
sourceMapIn: 'build/<%= pkg.name %>.js.map', | ||
sourceMapName: 'build/<%= pkg.name %>.min.js.map' | ||
} | ||
} | ||
}, | ||
karma: { /////////////////////////////////////////////////////////////////////////////////// | ||
options: { | ||
configFile: 'test/karma.conf.js' | ||
}, | ||
build: { browsers: ['PhantomJS'] }, | ||
}, | ||
docker: { ////////////////////////////////////////////////////////////////////////////////// | ||
build: { | ||
src: ["src/**/*.js", "README.md", 'docs/*.md'], | ||
dest: "docs/docker", | ||
options: { | ||
colourScheme: 'borland', | ||
ignoreHidden: true, | ||
exclude: 'src/__prologue__.js,src/__epilogue__.js' | ||
} | ||
} | ||
} | ||
}); | ||
// Load tasks. ///////////////////////////////////////////////////////////////////////////////////// | ||
grunt.loadNpmTasks('grunt-concat-sourcemap'); | ||
grunt.loadNpmTasks('grunt-karma'); | ||
grunt.loadNpmTasks('grunt-contrib-uglify'); | ||
grunt.loadNpmTasks('grunt-docker'); | ||
|
||
// Register tasks. ///////////////////////////////////////////////////////////////////////////////// | ||
grunt.registerTask('compile', ['concat_sourcemap:build', 'uglify:build']); | ||
grunt.registerTask('test', ['compile', 'karma:build']); | ||
grunt.registerTask('build', ['test', 'docker:build']); | ||
grunt.registerTask('default', ['build']); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
The MIT License | ||
=============== | ||
|
||
Source code for `sermat.js` is Copyright (C) 2015 [Leonardo Val](mailto:[email protected]). | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
Sermat.js | ||
========= | ||
|
||
Sermat is a serialization and data exchange format, similar to [JSON](http://json.org/). It is meant | ||
to be used when dealing with heavily marshalled interfaces separating the application being | ||
developed. Examples of this include the communtication between | ||
[web workers](http://www.whatwg.org/specs/web-workers/current-work/) or those and the rendering | ||
thread in browsers, or between [iframes](http://www.w3schools.com/html/html_iframe.asp). | ||
|
||
[![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/) | ||
|
||
[![NPM](https://nodei.co/npm/sermat.png)](https://www.npmjs.com/package/sermat) | ||
|
||
## Design | ||
|
||
Sermat goals are the following: | ||
|
||
+ _Extend JSON_: All valid JSON strings must be also valid Sermat strings, although the viceversa | ||
may not be true. | ||
|
||
+ _Allow custom types_: Sermat must be able to deal with instances of types other than the basic | ||
Javascript types (booleans, numbers, strings, arrays and object literals). Users must be able to | ||
register types to be used (like `Date` or user defined classes), in order to serialize them | ||
properly and obtain an equivalent instance after parsing. | ||
|
||
+ _Handle structures with complicated references_: Users must be able to serialize (and afterwards | ||
properly materialize) data structures that are not strictly trees; i.e. values may be referenced | ||
more than once, even if that means a cycle of references. | ||
|
||
### Minor changes | ||
|
||
Sermat addresses some minor quirks of JSON. Firstly, serializing `undefined` values will raise an | ||
error, unless explicitly permitted. In that case `undefined` will be transformed to `null` in a | ||
consistent manner. | ||
|
||
```javascript | ||
JSON.stringify(undefined); // Results in undefined | ||
Sermat.serialize(undefined); // Raises "Sermat.serialize: Cannot serialize undefined value!" | ||
Sermat.serialize(undefined, Sermat.ALLOW_UNDEFINED); // Results in "null" | ||
|
||
JSON.stringify({a:undefined}); // Results in "{}" | ||
Sermat.serialize({a:undefined}, Sermat.ALLOW_UNDEFINED); // Results in "{a:null}" | ||
JSON.stringify([undefined]); // Results in "[null]" | ||
Sermat.serialize([undefined], Sermat.ALLOW_UNDEFINED); // Results in "[null]" | ||
``` | ||
|
||
`Infinity` and `NaN` values are allowed, as well as comments, using the block comment syntax of | ||
Javascript. Strings may have multiple lines between the double quotes. Also, some escape sequences | ||
that are valid in Javascript but not in JSON are accepted by Sermat (e.g. `'\v'` or `'\xA9'`). Keys | ||
in object literals don't have to be between double quotes if they comply with [Javascript's rules | ||
for identifiers](http://www.w3schools.com/js/js_variables.asp) and if all characters are in the | ||
range `[\x00-\x7F]` (dots and dashes are also allowed). | ||
|
||
### Constructions | ||
|
||
One of the more important aspects of Sermat are _constructions_: a way of customizing serialization | ||
and materialization for particular types. The user may register custom methods for serializing and | ||
materializing objects built with a given constructor (e.g. `Date`). These objects will be written | ||
in text form in a similar way a function call is written in Javascript. | ||
|
||
```javascript | ||
Sermat.serialize(new Date()); // Results like this: 'Date(2015,6,5,6,33,47,123)'. | ||
Sermat.serialize(/\d+/g); // Results in: 'RegExp("\\\\d+","g")'. | ||
``` | ||
|
||
When parsed, the result will be a properly initialized instance of the corresponding type. Some | ||
Javascript base types are implemented _out-of-the-box_. Implementations for custom types can be | ||
defined with `Sermat.register` or adding a `__SERMAT__` member to the constructor. In the following | ||
example the identifier is defined to be `mylib.Point2D`, instead of the default `Point2D`. | ||
identifiers cannot have dots, it is necessary to write it between double quotes. | ||
|
||
```javascript | ||
function Point2D(x, y) { | ||
this.x = +x; | ||
this.y = +y; | ||
} | ||
Sermat.serialize(new Point2D(44, 173)); // Raises "Sermat.serialize: Cannot serialize value!" | ||
Point2D.__SERMAT__ = { | ||
identifier: "mylib.Point2D", | ||
serializer: function serialize_Point2D(obj) { | ||
return [obj.x, obj.y]; | ||
}, | ||
materializer: function materialize_Point2D(obj, args) { | ||
return args && (new Point2D(+args[0], +args[1])); | ||
} | ||
}; | ||
Sermat.register(Point2D); | ||
Sermat.serialize(new Point2D(44, 173)); // Results in: 'mylib.Point2D(44,173)' | ||
``` | ||
|
||
### References | ||
|
||
Sermat by default does not allow objects to be serialized more than once. Having the same object as | ||
a component in more than one place causes an error. For example: | ||
|
||
```javascript | ||
var obj1 = {a: 7}; | ||
Sermat.serialize([obj1, obj1]); // Raises "Sermat.serialize: Repeated reference detected!" | ||
``` | ||
|
||
This behaviour can be changed in two ways. The first one is simply to allow values to be serialized | ||
more than once, like JSON does. | ||
|
||
```javascript | ||
JSON.stringify([obj1, obj1]); // Results in '[{"a":7},{"a":7}]'. | ||
Sermat.serialize([obj1, obj1], Sermat.ALLOW_REPEATED); // Results in '[{a:7},{a:7}]'. | ||
``` | ||
|
||
The second one is part of another important feature called _bindings_. This is a syntax that allows | ||
to bind values to identifiers (starting with `$`) so they can be reused in another place. When | ||
parsed the resulting data structure is an acyclic graph instead of a tree. | ||
|
||
```javascript | ||
Sermat.serialize([obj1, obj1], Sermat.ALLOW_BINDINGS); // Results in '$0=[$1={a:7},$1]'. | ||
``` | ||
|
||
Circular references are not supported by only allowing bindings. To make this work, circular | ||
references have to be allowed explicitly. | ||
|
||
```javascript | ||
obj1.b = obj1; | ||
Sermat.serialize([obj1, obj1], Sermat.ALLOW_BINDINGS); // Raises "Sermat.serialize: Circular reference detected!" | ||
Sermat.serialize([obj1, obj1], Sermat.ALLOW_CIRCULAR); // Results in '$0=[$1={a:7,b:$1},$1]'. | ||
``` | ||
|
||
Circular reference support in constructions requires the materializer functions to follow this | ||
protocol. If a new instance must be built the `obj` argument will be `null`, else it will have an | ||
instance already built to initialize. If an empty instance must be built the `args` argument will be | ||
`null`, else it will have the arguments for the objects constructor (either with or without `new`). | ||
|
||
When a construction is being parsed (after the identifier and before its arguments) the | ||
corresponding materializer is called without arguments (`obj` and `args` both equal to `null`). If a | ||
new _empty_ instance can be built it must be returned. The materializer will be called again later | ||
(after the arguments have been parsed) with `obj` equal to this result, so the new instance can be | ||
properly initialized. If the materializer cannot build an _empty_ instance, it must returns `null`. | ||
This defers building the new object to after the arguments have been parsed, but then circular | ||
references cannot be properly parsed. | ||
|
||
This example show both cases. It uses the `sermat` function, which basically serializes a value and | ||
then materializes it back, effectively cloning it. | ||
|
||
```javascript | ||
function Refs(refs) { | ||
this.refs = Array.isArray(refs) ? refs : refs ? [refs] : []; | ||
} | ||
Refs.ALLOW_EMPTY_INSTANCES = false; | ||
Sermat.register(Refs, | ||
function serialize_Refs(obj) { | ||
return obj.refs; | ||
}, | ||
function materialize_Refs(obj, args) { | ||
if (args === null) { | ||
return Refs.ALLOW_EMPTY_INSTANCES ? (new Refs()) : null; | ||
} else if (obj !== null) { | ||
Refs.call(obj, args); | ||
return obj; | ||
} else { | ||
return new Refs(args); | ||
} | ||
} | ||
); | ||
var refs1 = new Refs(obj1); | ||
refs1.refs.push(refs1); | ||
Sermat.sermat(refs1, Sermat.ALLOW_CIRCULAR); // Raises "Sermat.materialize: '$xx' is not bound at ...!". | ||
Refs.ALLOW_EMPTY_INSTANCES = true; | ||
Sermat.sermat(refs1, Sermat.ALLOW_CIRCULAR); // Returns a copy of refs1. | ||
``` | ||
|
||
## License | ||
|
||
Sermat is open source software, licenced under an [MIT license](LICENSE.md) (see LICENSE.md). | ||
|
||
## Contact | ||
|
||
Suggestions and comments are always welcome at [[email protected]](mailto:[email protected]). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
Sermat.js pending list | ||
====================== | ||
|
||
+ Pretty printing capabilities, like the third parameter of `JSON.stringify`. | ||
|
||
+ Add more Javascript base types to `CONSTRUCTIONS`. |
Oops, something went wrong.