├── eslint.config.js ├── tests ├── data │ ├── file7.jsox │ ├── file4.jsox │ ├── file2.err1.jsox │ ├── testQuotes.jsox │ ├── file6.jsox │ ├── file3.jsox │ ├── file8.jsox │ ├── test-message-1.jsox │ ├── file2.jsox │ ├── file2a.jsox │ ├── file5.jsox │ ├── test.bat │ ├── file5.error.jsox │ ├── file2.stream.jsox │ ├── file1.jsox │ ├── test.js │ ├── rawtest.js │ ├── stest.js │ ├── rawtest.mjs │ ├── nested.jsox │ ├── testReferenceRevive.jsox │ ├── tasks.jsox │ ├── test_1.2.114.jsox │ └── testReferenceRevive2.jsox ├── testJsonDecode.js ├── test-single-json6.js ├── testContinuity.js ├── testDateTime.js ├── json6BufferTest.js ├── stream.json ├── testParseNoQuoteString.js ├── testNullKeyword.js ├── json_encode_nul.js ├── testFieldSpacing.js ├── stringify │ ├── testMapType.js │ ├── testClassStringify.js │ ├── testExternRef.js │ ├── testTypeArray.js │ ├── testArrayStringify.js │ └── testStringify.js ├── testSUnicode.js ├── json6ObjectCommaTest.js ├── github-issue-3.js ├── test_object_field_encoding.js ├── map │ └── testMapEncode.js ├── testEmpty.js ├── streamTest.js ├── json6TestObjectArray.js ├── testPUnicode.js ├── stringBench.js ├── dateTest.mjs ├── peg │ └── testjsox.js ├── testTypeArray.js ├── testCustomType.js ├── dateTest.js ├── benchmark │ ├── bench1a.js │ └── bench1.js ├── objectProto │ └── testProto.js ├── testUnicode.js ├── newTest │ └── testbuf.js ├── json6StreamTest.js ├── test_array_subref.js ├── json6BadTest.js ├── numberTest.js ├── json6StringTest.js ├── testRef3.js ├── testNumberConvert.js ├── testNumberConvertPlus.js ├── json6TestObject2.js ├── TestObjectKeys.js ├── json6NumberTest.js ├── testjson6.js └── srg_prefix.js ├── .gitignore ├── Val.GIF ├── parser.GIF ├── lib ├── index.js ├── jsox.es6.js.gz ├── jsox.min.js.gz ├── jsox.min.mjs.gz ├── makeTypes3.bat ├── makeTypes.bat ├── makeTypes2.bat ├── mk.bat ├── cli.js ├── require.js └── jsox.min.d.ts ├── JSOX-Value.GIF ├── JSOX-Value.pdn ├── JSOX-Value.png ├── JSOX-Value2.gif ├── JSOX-Value2.png ├── NumberRule.GIF ├── test ├── jsoxTest.js ├── bootstrap │ ├── node.js │ └── node ├── test1.bat ├── 1.2.106-require.jsox ├── stream.json6 ├── test-single-json6.js ├── testJsonDecode.js ├── escape.js ├── issue-9.js ├── 1.2.106-require.js ├── 1.2.104.js ├── 1.2.109-regexp.mjs ├── 1.2.109-regexp.js ├── sack-vfs-1.0.1007.mjs ├── 1.2.107-base64.js ├── 1.2.115.js ├── testa.js ├── 1.2.107-base64.mjs ├── benchmarks │ ├── fundamentals │ │ ├── stringBench.js │ │ └── testNumberConvert.js │ ├── json6Test.js │ ├── json6StringTest.js │ ├── json6ObjectArrays.js │ └── json6NumberTest.js ├── testIncompleteStringEscapes.js ├── 1.2.101.js ├── 1.2.106-require.mjs ├── 1.2.121.js ├── 1.2.117.js ├── 1.2.122.js ├── 1.2.113-DateNS.js ├── 1.2.104-stringify.js ├── sack-vfs-1.0.1013.mjs ├── 1.2.104-macro-tag.js ├── sack-vfs-1.0.1007-base64.mjs ├── 1.2.113-DateNS.mjs ├── 1.2.102.js ├── 1.2.102.mjs ├── 1.2.103.js ├── json6TestObjectArray.js ├── numberTest.js ├── 1.2.108-fromJSOX.js ├── 1.2.106-base64.mjs ├── testObject.js ├── streamTest.js ├── json6TestObject2.js ├── 1.2.114.js ├── 1.2.114.mjs ├── stringEscapes.js ├── 1.2.108-nestedFinal.js ├── 1.2.104-toFrom.js ├── jsoxStreamTest.js ├── testjson6.js ├── 1.2.108-nestedFinalInstanced.js ├── json6BadTest.js └── TestObjectKeys.js ├── .eslintignore ├── .npmignore ├── .travis.yml ├── .eslintrc.json ├── test.js ├── test.mjs ├── json.bnf ├── LICENSE.md ├── rollup.config.js ├── package.json ├── package.jsox ├── jsox.bnf └── jsox2.ebnf /eslint.config.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/data/file7.jsox: -------------------------------------------------------------------------------- 1 | { "a(5)":"Fail"} 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | xx 3 | zz* 4 | node_modules 5 | -------------------------------------------------------------------------------- /Val.GIF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d3x0r/JSOX/HEAD/Val.GIF -------------------------------------------------------------------------------- /parser.GIF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d3x0r/JSOX/HEAD/parser.GIF -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | module.exports = require('./jsox.js'); 3 | -------------------------------------------------------------------------------- /JSOX-Value.GIF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d3x0r/JSOX/HEAD/JSOX-Value.GIF -------------------------------------------------------------------------------- /JSOX-Value.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d3x0r/JSOX/HEAD/JSOX-Value.pdn -------------------------------------------------------------------------------- /JSOX-Value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d3x0r/JSOX/HEAD/JSOX-Value.png -------------------------------------------------------------------------------- /JSOX-Value2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d3x0r/JSOX/HEAD/JSOX-Value2.gif -------------------------------------------------------------------------------- /JSOX-Value2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d3x0r/JSOX/HEAD/JSOX-Value2.png -------------------------------------------------------------------------------- /NumberRule.GIF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d3x0r/JSOX/HEAD/NumberRule.GIF -------------------------------------------------------------------------------- /test/jsoxTest.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d3x0r/JSOX/HEAD/test/jsoxTest.js -------------------------------------------------------------------------------- /lib/jsox.es6.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d3x0r/JSOX/HEAD/lib/jsox.es6.js.gz -------------------------------------------------------------------------------- /lib/jsox.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d3x0r/JSOX/HEAD/lib/jsox.min.js.gz -------------------------------------------------------------------------------- /lib/jsox.min.mjs.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d3x0r/JSOX/HEAD/lib/jsox.min.mjs.gz -------------------------------------------------------------------------------- /lib/makeTypes3.bat: -------------------------------------------------------------------------------- 1 | call tsc jsox.min.js --target esnext --declaration --allowJs --emitDeclarationOnly 2 | -------------------------------------------------------------------------------- /test/bootstrap/node.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const chai = require('chai'); 3 | global.expect = chai.expect; 4 | -------------------------------------------------------------------------------- /lib/makeTypes.bat: -------------------------------------------------------------------------------- 1 | call tsc jsox.mjs --target esnext --declaration --allowJs --emitDeclarationOnly --stripInternal 2 | -------------------------------------------------------------------------------- /test/bootstrap/node: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import('chai').then( (module)=>{ 3 | global.expect = module.expect 4 | }); 5 | -------------------------------------------------------------------------------- /test/test1.bat: -------------------------------------------------------------------------------- 1 | mocha --experimental-loader=../lib/import.mjs --require bootstrap/node --require ../lib/require.js %* 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | lib/*es3* 2 | lib/*es6* 3 | lib/*.min.* 4 | test.js 5 | test/* 6 | tests/* 7 | lib/jsox.js 8 | rollup.config.js 9 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *~ 2 | lib/mk.bat 3 | lib/*~ 4 | tests 5 | test 6 | coverage 7 | 8 | makeUnicodeNonIdent.js 9 | parser.md 10 | -------------------------------------------------------------------------------- /test/1.2.106-require.jsox: -------------------------------------------------------------------------------- 1 | { 2 | desc: "configuration file to read", 3 | date: 2021-01-02T00:00:00Z, 4 | value:123 5 | } 6 | -------------------------------------------------------------------------------- /tests/testJsonDecode.js: -------------------------------------------------------------------------------- 1 | 2 | var JSON6=require( ".." ); 3 | console.log( "MNOP=", JSON6.parse( '"\\u004D\\u004e\\u004F\\u0050"' ) ); 4 | -------------------------------------------------------------------------------- /tests/data/file4.jsox: -------------------------------------------------------------------------------- 1 | p{ x , y } 2 | r{ o , n } 3 | object{ p, motion, color } 4 | object{ p{6,3}, r{p{1,2},p{3,4}}, "white" } -------------------------------------------------------------------------------- /tests/data/file2.err1.jsox: -------------------------------------------------------------------------------- 1 | card { author, title } 2 | [ card{ "bob", "book" }, 3 | card{ "tom", "cool" }, 4 | card{ "ted", "mule" } 5 | ] 6 | -------------------------------------------------------------------------------- /tests/data/testQuotes.jsox: -------------------------------------------------------------------------------- 1 | 2 | { a:1234, b:{"a":123 }} 3 | a{a,b}{ a:1234, b:{"a":123 },c:a{3,4} } 4 | { a:1234, b:{"a":123 }} 5 | { a:1234, b:{"a":123 }} 6 | -------------------------------------------------------------------------------- /tests/test-single-json6.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var JSON6 = require( ".." ); 4 | 5 | var obj = JSON6.parse( "{ asdf : 1234 } " ); 6 | console.log( "Got:", obj ); 7 | 8 | -------------------------------------------------------------------------------- /tests/testContinuity.js: -------------------------------------------------------------------------------- 1 | var JSOX=require( ".." ); 2 | console.log( "{data:0,classTest:{b:1,c:2,d:3}}=", JSOX.parse( 'abc{b,c,d}{data:0,classTest:abc{1,2,3}}' ) ); 3 | -------------------------------------------------------------------------------- /tests/testDateTime.js: -------------------------------------------------------------------------------- 1 | const JSOX = require(".." ); 2 | 3 | console.log( "Iso", new Date().toISOString() ); 4 | console.log( "jsox", JSOX.stringify( new Date() ) ); -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | # - 10 5 | - 12 6 | - 14 7 | - 16 8 | 9 | before_install: 10 | - export TZ=Canada/Pacific 11 | -------------------------------------------------------------------------------- /tests/json6BufferTest.js: -------------------------------------------------------------------------------- 1 | 2 | var JSON = require( ".." ); 3 | 4 | var buf1 = new Buffer( "{op:'json'}" ); 5 | console.log( buf1 ); 6 | 7 | console.log( JSON.parse( buf1 ) ); 8 | -------------------------------------------------------------------------------- /test/stream.json6: -------------------------------------------------------------------------------- 1 | 123 2 | 456 3 | 789 4 | 1234 5 | ['a','b','c'] 6 | `This 7 | is 8 | a 9 | test` 10 | { a: { b : { c : { d : 123 }, e: [154,452] }, f : 942 }, g: 'Final' } 11 | -------------------------------------------------------------------------------- /tests/stream.json: -------------------------------------------------------------------------------- 1 | 123 2 | 456 3 | 789 4 | 1234 5 | ['a','b','c'] 6 | `This 7 | is 8 | a 9 | test` 10 | { a: { b : { c : { d : 123 }, e: [154,452] }, f : 942 }, g: 'Final' } 11 | 12 | -------------------------------------------------------------------------------- /tests/testParseNoQuoteString.js: -------------------------------------------------------------------------------- 1 | const JSOX = require( ".." ); 2 | 3 | const o = JSOX.parse ('{op:f,id:2,ret:"mAOyCJ59I3Y0$79Z_B2y0uM6ofFk$$OQnvf4MZsRSS0="}' ) 4 | console.log( "o:", o ); 5 | -------------------------------------------------------------------------------- /lib/makeTypes2.bat: -------------------------------------------------------------------------------- 1 | :call tsc jsox.js --target esnext --declaration --allowJs --emitDeclarationOnly 2 | 3 | call tsc jsox.js --declaration --allowJs --emitDeclarationOnly --stripInternal 4 | 5 | -------------------------------------------------------------------------------- /tests/testNullKeyword.js: -------------------------------------------------------------------------------- 1 | const util = require('util'); 2 | const JSOX = require(".."); 3 | 4 | const obj = JSOX.parse( "[null,null,null, null , null,null ,null]" ); 5 | console.log( "object:", obj ); 6 | -------------------------------------------------------------------------------- /tests/data/file6.jsox: -------------------------------------------------------------------------------- 1 | { 2 | company : { name : "Example.com", 3 | employees : [ { name:"bob" },{name:"tom"} ], 4 | manager : ref["company","employees",0] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/json_encode_nul.js: -------------------------------------------------------------------------------- 1 | 2 | var JSON = require( ".." ); 3 | 4 | var input = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 5 | var output = JSON.escape( input ); 6 | console.log( "string:", input, "becomes:", output ); 7 | 8 | -------------------------------------------------------------------------------- /tests/testFieldSpacing.js: -------------------------------------------------------------------------------- 1 | 2 | var JSOX = require(".."); 3 | 4 | try { 5 | console.log( JSON.stringify( JSOX.parse( " { a : true } " ) ) ) ; 6 | }catch(err) { 7 | console.log( err ); 8 | } 9 | -------------------------------------------------------------------------------- /tests/data/file3.jsox: -------------------------------------------------------------------------------- 1 | p{ x , y } 2 | r{ o , n } 3 | 4 | r{p{5,10},p{2,7}} 5 | { position: p{1, 2}, 6 | data : r{ p{ 0,0}, p{1, 0 } } // nested usage 7 | } 8 | 9 | p:{x,y,z} 10 | r{p{5,10,-1},p{2,7,1}} 11 | -------------------------------------------------------------------------------- /tests/stringify/testMapType.js: -------------------------------------------------------------------------------- 1 | var JSOX=require( "../.." ); 2 | 3 | var m = new Map(); 4 | var o = {keys:m}; 5 | 6 | m.set( "asdf", {obj1:0} ); 7 | 8 | console.log( "map only", JSOX.stringify( m ) ); 9 | console.log( "object", JSOX.stringify( o ) ); 10 | -------------------------------------------------------------------------------- /tests/testSUnicode.js: -------------------------------------------------------------------------------- 1 | 2 | var JSOX = require( ".." ) 3 | 4 | process.stdin.on('data', processLine ); 5 | 6 | function processLine (line) { 7 | line = line.toString( 'utf8' ); 8 | var out; 9 | { console.log( out = JSON.stringify(line.split(""))); } 10 | } 11 | -------------------------------------------------------------------------------- /test/test-single-json6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSON6 = require( ".." ); 3 | 4 | describe('Single JSON6', function () { 5 | it('Single JSON6', function () { 6 | expect(JSON6.parse( "{ asdf : 1234 } " )).to.deep.equal({ 7 | asdf: 1234 8 | }); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /tests/data/file8.jsox: -------------------------------------------------------------------------------- 1 | color"0x21160b" 2 | stringTest"HelloWorld" 3 | { a: stringTest"HelloWorld" } 4 | 5 | arrayTest[1,2,3] 6 | 7 | objectTest{a,b,c} 8 | objectTest{1,2,3} 9 | 10 | objectTest2{a,b,c} 11 | objectTest2{6,7,8} 12 | 13 | [1,2,3,4,5,6,7,[1,2,3,4,5,[4,3,2,1]]] 14 | -------------------------------------------------------------------------------- /tests/data/test-message-1.jsox: -------------------------------------------------------------------------------- 1 | {id:QHVXQmJqAT$UFk__,op:updateTask,task:{altbin:'',arg:'',args:["--experimental-loader=sack.vfs/import.mjs","main.mjs"],bin:node,dependson:'',env:{'':daubbers,SITE:''},name:"Daubbers Launcher (8120)",noautorun:false,restarts:false,serviceName:'',work:"..\\daubbers"}} -------------------------------------------------------------------------------- /tests/json6ObjectCommaTest.js: -------------------------------------------------------------------------------- 1 | 2 | var JSON = require( ".." ); 3 | console.log( "excessive minus signs:", JSON.parse( "----1234" ) ); 4 | console.log( "excessive minus signs:", JSON.parse( "--++-+-1234" ) ); 5 | console.log( "excessive commas:", JSON.parse( "{ a:1234,,,,,b:456 }" ) ); 6 | 7 | -------------------------------------------------------------------------------- /tests/github-issue-3.js: -------------------------------------------------------------------------------- 1 | 2 | var JSOX = require( ".." ); 3 | var input = "{use:[['less',{includePath:['$PWD/packages/ufc-host-app/src']}]]}" 4 | 5 | console.log( "object:", JSOX.parse( input ) ); 6 | 7 | console.log( "Test Output1 : \n", JSON.stringify( JSOX.parse( input ) ), "\n", input ); 8 | 9 | -------------------------------------------------------------------------------- /tests/data/file2.jsox: -------------------------------------------------------------------------------- 1 | card{ author, title } 2 | { otherCards: { example : card{"jim","jsox"} }, 3 | cards : [ card { "bob", "book" }, // spaces are legal 4 | card { "tom", "cool" }, 5 | card { "ted", "mule" }, 6 | ], 7 | out : ref["cards",1] 8 | } 9 | -------------------------------------------------------------------------------- /tests/data/file2a.jsox: -------------------------------------------------------------------------------- 1 | card{ author, title } 2 | [ card{ "bob", "book" }, 3 | card{ "tom", "cool" }, 4 | card{ "ted", "mule" } 5 | ] 6 | 1 7 | 2 8 | 3 9 | 4 5 6 10 | 7e3 11 | "8 9 10" jkl "11" "12" 12 | "13" 13 | ghi 14 | "14" 15 | asdf 16 | ["15"] 17 | ["16","17"] 18 | {"18":"19"} 19 | {"20":"21","22":"23"} -------------------------------------------------------------------------------- /tests/test_object_field_encoding.js: -------------------------------------------------------------------------------- 1 | var JSOX = require( ".." ); 2 | 3 | const obj = { '0abc' : true, 4 | 'a3456=' : true, 5 | 'a+b' : true, 6 | '.abc' : true, 7 | }; 8 | 9 | console.log( "recode:", JSOX.stringify( JSOX.parse( JSOX.stringify(obj)) ) ); 10 | console.log( "output:", JSOX.stringify( obj ) ) 11 | -------------------------------------------------------------------------------- /tests/data/file5.jsox: -------------------------------------------------------------------------------- 1 | { 2 | a: { name: "a" }, 3 | b: { name: "b" }, 4 | pair : [ref["a"],ref["b"]] 5 | } 6 | 7 | { 8 | company : { name : "Example.com", 9 | employees : [ { name:"bob" },{name:"tom"} ], 10 | manager : ref["company","employees",0] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/map/testMapEncode.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var JSOX = require( "../.." ) 4 | 5 | var m= new Map(); 6 | m.set( "This", true ); 7 | m.set( "Is", 123 ); 8 | m.set( "A", "567" ); 9 | m.set( "Test", new Date() ); 10 | 11 | var ms = JSOX.stringify( m ); 12 | console.log( "out:", ms ); 13 | console.log( "out/in:", JSOX.parse( ms ) ); 14 | -------------------------------------------------------------------------------- /test/testJsonDecode.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSON6 = require( ".." ); 3 | 4 | describe('JSON decoding', function () { 5 | it('Unicode escapes', function () { 6 | const result = JSON6.parse( '"\\u004D\\u004e\\u004F\\u0050"' ); 7 | //console.log( "MNOP=", result ); 8 | expect(result).to.equal('MNOP'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /tests/testEmpty.js: -------------------------------------------------------------------------------- 1 | 2 | const JSOX=require('..'); 3 | 4 | var s; 5 | 6 | s = JSOX.stringify(JSOX.parse( '{ a:1 , b:3 , c:[1,3,] , }' )); 7 | console.log( s ); 8 | 9 | s = JSOX.stringify(JSOX.parse( '{ a:1 , b:3 , c:[1,3,,] , }' )); 10 | console.log( s ); 11 | 12 | s = JSOX.stringify(JSOX.parse( '{ ,,, a:1,,,,b:3,,, }' )); 13 | console.log( s ); 14 | -------------------------------------------------------------------------------- /tests/data/test.bat: -------------------------------------------------------------------------------- 1 | node rawtest.js ./file1.jsox 2 | node rawtest.js ./file2.jsox 3 | node rawtest.js ./file3.jsox 4 | node rawtest.js ./file4.jsox 5 | node rawtest.js ./file5.jsox 6 | node rawtest.js ./file6.jsox 7 | node rawtest.js ./file7.jsox 8 | node rawtest.js ./file8.jsox 9 | node rawtest.js ./testReferenceRevive.jsox 10 | node rawtest.js ./testQuotes.jsox 11 | -------------------------------------------------------------------------------- /tests/streamTest.js: -------------------------------------------------------------------------------- 1 | 2 | var JSON6 = require( '..' ); 3 | var fs = require( 'fs' ); 4 | 5 | var buf = fs.readFileSync( 'stream.json' ); 6 | var msg = buf.toString( 'utf8' ); 7 | var parser = JSON6.begin( (val)=>{ 8 | console.log( "Got Object:", val ); 9 | }) 10 | 11 | parser.write({}); 12 | 13 | for( var result = parser.write( msg ); 14 | result > 0; parser.write() ); 15 | 16 | -------------------------------------------------------------------------------- /test/escape.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSON6 = require( ".." ); 3 | 4 | describe('JSON6.escape', function () { 5 | it('Escapes', function () { 6 | const str = JSON6.escape('a"b\\c`d\'e'); 7 | expect(str).to.equal('a\\"b\\\\c\\`d\\\'e'); 8 | }); 9 | it('Handles empty string', function () { 10 | const str = JSON6.escape(''); 11 | expect(str).to.equal(''); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /tests/data/file5.error.jsox: -------------------------------------------------------------------------------- 1 | { 2 | a: { name: "a" }, 3 | b: { name: "b" }, 4 | pair : [ref["a"],ref["b"]] 5 | } 6 | 7 | { 8 | company : { name : "Example.com", 9 | employees : [ { name:"bob" },{name:"tom"} ], 10 | manager : ref["company","exploees",0] // should this throw? Right now it returns undefind from C, and faults in JS 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/data/file2.stream.jsox: -------------------------------------------------------------------------------- 1 | card{ author, title } 2 | { otherCards: { example : card{"jim","jsox"} }, 3 | cards : [ card { "bob", "book" }, // spaces are legal 4 | card{ "tom", "cool" }, 5 | card{ "ted", "mule" }, 6 | ], 7 | out : ref["cards",1] 8 | } 9 | [ card{ "bob", "book" }, 10 | card{ "tom", "cool" }, 11 | card{ "ted", "mule" } 12 | ] 13 | -------------------------------------------------------------------------------- /tests/json6TestObjectArray.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var JSON6 = require('..') 4 | var d = '[ {a: "", b: ""}, {a: "", b: ""} ]'; 5 | console.log( JSON6.parse( d ) ); 6 | 7 | var arr2 = "[1,[2,[3,[4,5]]]]"; 8 | console.log( JSON6.parse( arr2 ) ); 9 | 10 | 11 | var d = '[ {a: "", b: ""}, [1,2], {a: "", b: ""} ]'; 12 | console.log( JSON6.parse( d ) ); 13 | 14 | var d = '{ a:{a: "", b: ""}, b:[{d:"",e:""},{f:"",g:""}], c:{a: "", b: ""} }'; 15 | console.log( JSON6.parse( d ) ); 16 | -------------------------------------------------------------------------------- /test/issue-9.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | const JSOX = require( ".." ); 4 | 5 | 6 | describe('Issue 9', function () { 7 | 8 | it( 'parses 1', function() { 9 | expect( JSOX.parse('{a:"",b:[{c:[{d:false}]}],e:"TEST"}' )).to.deep.equal({a:"",b:[{c:[{d:false}]}],e:"TEST"}) 10 | } ); 11 | it( 'parses 2', function() { 12 | expect( JSOX.parse('{a:"",b:[{c:[{d:false}]}]}' )).to.deep.equal({a:"",b:[{c:[{d:false}]}]}) 13 | } ); 14 | 15 | } ); 16 | -------------------------------------------------------------------------------- /test/1.2.106-require.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | require( ".." ); 3 | //require( "../lib/require.js" ); 4 | 5 | describe('Added in 1.2.106 - require(cjs)', function () { 6 | 7 | it('allows using require on extension', function () { 8 | const config = require( "./1.2.106-require.jsox" ); 9 | expect( config ).to.deep.equal( { 10 | desc: "configuration file to read", 11 | date : new Date( "2021-01-02T00:00:00Z" ), 12 | value:123} 13 | ); 14 | } ); 15 | } ); 16 | -------------------------------------------------------------------------------- /tests/testPUnicode.js: -------------------------------------------------------------------------------- 1 | 2 | var JSOX = require( ".." ) 3 | 4 | process.stdin.on('data', processLine ); 5 | 6 | //var line = require( 'fs').readFileSync(0); // STDIN_FILENO = 0 7 | //console.log(stdinBuffer.toString()); 8 | 9 | //process.stdin.pipe(require('split')()).on('data', processLine) 10 | //processLine(line) 11 | 12 | function processLine (line) { 13 | line = line.toString( 'utf8' ); 14 | { const s = JSON.parse(line).join(""); console.log(s); } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /test/1.2.104.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSON6 = require( ".." ); 3 | 4 | describe('JSON6.forgiving leading `+` ', function () { 5 | it('accepts `+ 8`', function () { 6 | expect( JSON6.parse( '+ 8' ) ).to.equal( 8 ); 7 | } ); 8 | it('accepts `+ Infinity`', function () { 9 | expect( JSON6.parse( '+ Infinity' ) ).to.equal( Infinity ); 10 | } ); 11 | it('throws `123+44`', function () { 12 | expect( function() { JSON6.parse( '123+44' ); } ).to.throw( Error ); 13 | } ); 14 | } ); 15 | -------------------------------------------------------------------------------- /tests/stringBench.js: -------------------------------------------------------------------------------- 1 | 2 | var string = "012359599323"; 3 | 4 | var start = Date.now(); 5 | for( var m = 0; m < 10000; m++ ) 6 | for( var n = 0; n < 100000; n++ ) 7 | if( string[0] === '0' ); 8 | var end = Date.now(); 9 | console.log( "1m in ", end-start ); 10 | 11 | 12 | var start = Date.now(); 13 | for( var m = 0; m < 10000; m++ ) 14 | for( var n = 0; n < 100000; n++ ) 15 | if( string.charCodeAt(0) === 48 ); 16 | var end = Date.now(); 17 | 18 | console.log( "1m in ", end-start ); 19 | -------------------------------------------------------------------------------- /test/1.2.109-regexp.mjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import {JSOX} from "jsox"; 3 | 4 | 5 | describe('Added in 1.2.109 (regexp)', function () { 6 | 7 | 8 | 9 | it( 'handles stringify', function() { 10 | 11 | const obj = /a+/; 12 | const strObj = JSOX.stringify( obj ); 13 | expect( strObj ).to.equal( "regex'a+'" ); 14 | }); 15 | 16 | it( 'handles parse', function() { 17 | const str = "regex'a+'"; 18 | const objStr = JSOX.parse( str ); 19 | expect( objStr).to.deep.equal( /a+/ ); 20 | } ); 21 | 22 | } ); -------------------------------------------------------------------------------- /tests/dateTest.mjs: -------------------------------------------------------------------------------- 1 | 2 | import {JSOX} from "../lib/jsox.mjs"; 3 | 4 | console.log( "Date:", JSOX.stringify( new Date() ) ); 5 | const wasDate = JSOX.parse( "2020-11-22T11:08:09.415-08:00" ); 6 | console.log( "Date:", wasDate ); 7 | 8 | const test = '{TaxId:[{tag:SSN,value:"123-456-7890"}],addresses:[],bankAccounts:[],contact:[],data:ref[],dob:2020-11-21T21:55:05.596-06:00,email:[],fName:Test,fmtName:"",lName:User,mName:M,nName:"",suffix:"",title:"Mr.",webAccounts:[]}'; 9 | const out = JSOX.parse( test ); 10 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es2021": true 6 | }, 7 | "overrides": [ 8 | { 9 | "files": [ "lib/cli.js" ], 10 | "env": { 11 | "node":true, 12 | "es2021": true 13 | } 14 | } 15 | ], 16 | "extends": "eslint:recommended", 17 | "parserOptions": { 18 | "ecmaVersion": 12 19 | }, 20 | "rules": { 21 | "no-mixed-spaces-and-tabs": ["error","smart-tabs"] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/1.2.109-regexp.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSOX = require( "../lib/jsox.js" ); 3 | 4 | 5 | describe('Added in 1.2.109 (regexp)', function () { 6 | 7 | it( 'handles stringify', function() { 8 | 9 | const obj = /a+/; 10 | const strObj = JSOX.stringify( obj ); 11 | expect( strObj ).to.equal( "regex'a+'" ); 12 | }); 13 | 14 | it( 'handles parse', function() { 15 | const str = "regex'a+'"; 16 | const objStr = JSOX.parse( str ); 17 | expect( objStr).to.deep.equal( /a+/ ); 18 | } ); 19 | 20 | } ); -------------------------------------------------------------------------------- /test/sack-vfs-1.0.1007.mjs: -------------------------------------------------------------------------------- 1 | import {JSOX} from "../lib/jsox.mjs"; 2 | 3 | 4 | describe('Added in 1.0.1007', function () { 5 | 6 | 7 | 8 | it( 'spaces around colons?', function() { 9 | //console.log( "Parsed:", JSOX.parse( '{\n\t"a" : "b", "c" : "d" }' ) ) 10 | //console.log( "Parsed:", JSOX.parse( '{\n\t"a" : "b", "c" : "d" }' ) ) 11 | expect( JSOX.parse( '{"a" : "b", "c" : "d" }' ) ) 12 | .to.deep.equal( {a:"b",c:"d"} ); 13 | // console.log( "Fail:", obj ); 14 | } ) 15 | } ) 16 | -------------------------------------------------------------------------------- /tests/stringify/testClassStringify.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var JSOX = require( "../.." ) 4 | 5 | var stringifier = JSOX.stringifier(); 6 | 7 | var obj = { author: "sam", Title : "All good books" }; 8 | var obj2 = { isle: 33, shelf : 4 }; 9 | 10 | stringifier.defineClass("card",obj); 11 | stringifier.defineClass("stk",obj2); 12 | 13 | var testArray = [obj,obj,obj,obj]; 14 | 15 | var r; 16 | 17 | r = stringifier.stringify( testArray ); 18 | console.log( r ); 19 | 20 | r = stringifier.stringify( testArray, null, 3 ); 21 | console.log( r ); 22 | -------------------------------------------------------------------------------- /test/1.2.107-base64.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const JSOX = require( ".." ); 4 | 5 | describe('Added in 1.2.107 - base64', function () { 6 | it('quotes numeric base64', function() { 7 | const ab = JSOX.parse( "ab['3abc']" ); 8 | const str = JSOX.stringify( ab ); 9 | expect( str).to.equal( "ab[\"3abc\"]" ); 10 | 11 | } ); 12 | it('skips quotes on alpha base64', function() { 13 | const ab = JSOX.parse( "ab['a3bc']" ); 14 | const str = JSOX.stringify( ab ); 15 | expect( str).to.equal( "ab[a3bc]" ); 16 | 17 | } ); 18 | } ); 19 | -------------------------------------------------------------------------------- /test/1.2.115.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | const JSOX = require( ".." ); 4 | 5 | describe('Added in 1.2.115', function () { 6 | 7 | 8 | 9 | it( 'recovers partial strings right', function() { 10 | const strings = ['Nbt']; 11 | const expects = strings.map( s=>JSOX.parse(s) ); 12 | for( let s=0; s < strings.length; s++ ) { 13 | if( strings[s] !== expects[s] ) throw new Error ( "Strings Should Match" ); 14 | } 15 | expect( "A" ).to.equal( "A" ); 16 | 17 | } ); 18 | 19 | } ); 20 | -------------------------------------------------------------------------------- /lib/mk.bat: -------------------------------------------------------------------------------- 1 | :call google-closure-compiler.cmd --language_out NO_TRANSPILE --js=jsox.js --js_output_file=jsox.es6.js 2 | :call google-closure-compiler.cmd --language_out ECMASCRIPT3 --js=jsox.js --js_output_file=jsox.es3.js 3 | :call google-closure-compiler.cmd --language_out ECMASCRIPT3 --formatting=pretty_print --js=jsox.js --js_output_file=jsox.es3.pretty.js 4 | :call google-closure-compiler.cmd --language_out NO_TRANSPILE --formatting=pretty_print --js=jsox.js --js_output_file=jsox.es6.pretty.js 5 | 6 | gzip -9 jsox.min.mjs -c >jsox.min.mjs.gz 7 | gzip -9 jsox.min.js -c > jsox.min.js.gz 8 | 9 | -------------------------------------------------------------------------------- /test/testa.js: -------------------------------------------------------------------------------- 1 | 2 | const JSON6 = require( ".." ); 3 | const JSOX = JSON6 4 | const parse = JSOX.parse; 5 | 6 | describe('Carriage return escape', function () { 7 | it( "drops", function() { 8 | expect( parse( "{ 'my \\\r key':3}" ) ).to.deep.equal( {'my key':3} ); 9 | }); 10 | }); 11 | 12 | describe('Unicode escape', function () { 13 | it('escapes unicode whitespace', function () { 14 | expect( parse( "'\\\u2028'" ).length ).to.equal( 0 ); 15 | } ); 16 | it('escapes unicode whitespace', function () { 17 | expect( parse( "'\\\u2029'" ).length ).to.equal( 0 ); 18 | } ); 19 | } ); -------------------------------------------------------------------------------- /test/1.2.107-base64.mjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import {JSOX} from "jsox"; 3 | //require( "../lib/require.js" ); 4 | 5 | import {default as config} from './1.2.106-require.jsox' 6 | 7 | describe('Added in 1.2.107 - base64', function () { 8 | it('quotes numeric base64', function() { 9 | const ab = JSOX.parse( "ab['3abc']" ); 10 | const str = JSOX.stringify( ab ); 11 | expect( str).to.equal( "ab[\"3abc\"]" ); 12 | 13 | } ); 14 | it('skips quotes on alpha base64', function() { 15 | const ab = JSOX.parse( "ab['a3bc']" ); 16 | const str = JSOX.stringify( ab ); 17 | expect( str).to.equal( "ab[a3bc]" ); 18 | 19 | } ); 20 | } ); 21 | -------------------------------------------------------------------------------- /tests/peg/testjsox.js: -------------------------------------------------------------------------------- 1 | 2 | var jsox = require( "../.." ); 3 | console.log( "JSOX:", jsox, Object.getPrototypeOf(jsox) ); 4 | 5 | var a = jsox.parse( '[Infinity,NaN,undefined,-Infinity,-123, {a:123}]' ); 6 | console.log( "out?", a ); 7 | console.log( "out?", JSON.stringify( a ) ); 8 | 9 | 10 | var a = jsox.parse( 'ident{object,field,names}ident{"abc",123,Infinity}' ); 11 | 12 | console.log( "out?", a ); 13 | 14 | var a = jsox.parse( 'ident{object,field,names}[ident{"abc",123,Infinity},ident{"abc",123,Infinity},ident{"abc",123,Infinity},ident{"abc",123,Infinity}]' ); 15 | 16 | console.log( "out?", a ); 17 | var a = jsox.parse( '[2018-09-11T09:11:09.011+07:00]' ); 18 | 19 | console.log( "out?", a ); 20 | -------------------------------------------------------------------------------- /tests/testTypeArray.js: -------------------------------------------------------------------------------- 1 | var JSOX=require( ".." ); 2 | 3 | console.log( "MNOP=", JSOX.parse( '{ab:ab["0123456"]}' ) ); 4 | console.log( "MNOP=", JSOX.parse( '{ab:u8["0123456789012345"]}' ) ); 5 | console.log( "MNOP=", JSOX.parse( '{ab:u16["01234565345"]}' ) ); 6 | console.log( "MNOP=", JSOX.parse( '{ab:u32["0123456789012345"]}' ) ); 7 | console.log( "MNOP=", JSOX.parse( '{ab:s8["0123456789012345"]}' ) ); 8 | console.log( "MNOP=", JSOX.parse( '{ab:s16["0123456789012345"]}' ) ); 9 | console.log( "MNOP=", JSOX.parse( '{ab:s32["0123456789012345"]}' ) ); 10 | console.log( "MNOP=", JSOX.parse( '{ab:f32["0123456789012345"]}' ) ); 11 | console.log( "MNOP=", JSOX.parse( '{ab:f64["00123456789012345123456789012345"]}' ) ); 12 | -------------------------------------------------------------------------------- /test/benchmarks/fundamentals/stringBench.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const string = "012359599323"; 4 | 5 | describe('String benchmarks', function () { 6 | this.timeout(10000); 7 | it('String index access', function () { 8 | const start = Date.now(); 9 | for( let m = 0; m < 10000; m++ ) 10 | for( let n = 0; n < 100000; n++ ) 11 | if( string[0] === '0' ); 12 | const end = Date.now(); 13 | console.log( "1m in ", end-start ); 14 | }); 15 | it('String charCode access', function () { 16 | const start = Date.now(); 17 | for( let m = 0; m < 10000; m++ ) 18 | for( let n = 0; n < 100000; n++ ) 19 | if( string.charCodeAt(0) === 48 ); 20 | const end = Date.now(); 21 | 22 | console.log( "1m in ", end-start ); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/benchmarks/json6Test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const JSON6 = require( "../../" ); 4 | 5 | describe('Benchmarking', function () { 6 | this.timeout(20000); 7 | it('Benchmarking', function () { 8 | const start = Date.now(); 9 | let result1, result2, result3; 10 | for( let n = 0; n < 1000000; n++ ) { 11 | result1 = JSON6.parse( "{\"a\":{\"b\":{\"c\":{\"d\":123}}}}" ); 12 | result2 = JSON6.parse( '"Simple String value"' ); 13 | result3 = JSON6.parse( '123456789' ); 14 | } 15 | 16 | const end = Date.now(); 17 | console.log( "1m in ", end - start ); 18 | expect(result1).to.deep.equal({ 19 | a: {b: {c: {d: 123}}} 20 | }); 21 | expect(result2).to.equal('Simple String value'); 22 | expect(result3).to.equal(123456789); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /tests/data/file1.jsox: -------------------------------------------------------------------------------- 1 | { a: "simple object", b:3, c:2018-09-11T09:33:02-07:00, d:123n, e:null, f:undefined, g:NaN, h:Infinity, i:-Infinity, j:-0.302, k:ab[faefa3BDa] 2 | , k2:ab[faefa3BDa3] // 3 isn't valid, should be 'w' to have the upper bits only set.. 3 | , k3:ab[faefa3BDa35] 4 | , k4:ab[faefa3BDa354] 5 | , k5:ab[faefa3BDa35=] 6 | , k6:ab[faefa3BDa3==] 7 | , k7:ab[faefa3BDa===] 8 | } 9 | 10 | /* 11 | k: 12 | ArrayBuffer { [Uint8Contents]: <7d a7 9f 6b 70 43>, byteLength: 6 }, 13 | k2: 14 | ArrayBuffer { [Uint8Contents]: <7d a7 9f 6b 70 43 6b>, byteLength: 7 }, 15 | k3: 16 | ArrayBuffer { [Uint8Contents]: <7d a7 9f 6b 70 43 6b 7e>, byteLength: 8 }, 17 | k4: 18 | ArrayBuffer { [Uint8Contents]: <7d a7 9f 6b 70 43 6b 7e 78>, byteLength: 9 } } 19 | */ -------------------------------------------------------------------------------- /tests/testCustomType.js: -------------------------------------------------------------------------------- 1 | var JSOX= require( ".." ); 2 | 3 | function Color() { 4 | this.r = 100; 5 | this.g = 150; 6 | this.b = 20; 7 | } 8 | Color.prototype.toString = function() { 9 | return '"--'+this.r.toString(16)+this.g.toString(16)+this.b.toString(16)+ '"'; 10 | } 11 | Color.prototype.toJSOX = function() { 12 | return '"#'+this.r.toString(16)+this.g.toString(16)+this.b.toString(16)+ '"'; 13 | } 14 | 15 | Color.prototype.fromJSOX = function() { 16 | return new Color(); 17 | } 18 | 19 | 20 | JSOX.registerToFrom( "color", Color.prototype, Color.prototype.toJSOX, Color.prototype.fromJSOX ); 21 | 22 | var c = new Color(); 23 | 24 | console.log( "Color:", JSOX.stringify( c ) ); 25 | console.log( "Color:", JSOX.parse(JSOX.stringify( c )) ); 26 | -------------------------------------------------------------------------------- /test/testIncompleteStringEscapes.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const JSON6 = require( ".." ); 4 | 5 | const parse = JSON6.parse; 6 | let o; 7 | 8 | describe('Incomplete String Escape tests', function () { 9 | 10 | expect(function () { 11 | o = parse( "'\\x1'" ); 12 | //console.log( "got back:", o ); 13 | }).to.throw(Error); 14 | 15 | it('Parses string octal escape followed by character', function () { 16 | const result = JSON6.parse( '"\\012"' ); 17 | expect(result).to.equal('\0' + '12'); 18 | }); 19 | 20 | expect(function () { 21 | o = parse( "'\\u31'" ); 22 | //console.log( "got back:", o ); 23 | }).to.throw(Error); 24 | 25 | expect(function () { 26 | o = parse( "'\\u{0'" ); 27 | //console.log( "got back:", o ); 28 | }).to.throw(Error); 29 | 30 | } ); 31 | -------------------------------------------------------------------------------- /test/1.2.101.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSOX = require( ".." ); 3 | 4 | 5 | describe('Added in 1.2.101', function () { 6 | 7 | it( 'Parses short unquoted value', function() { 8 | 9 | expect( JSOX.parse( '{fName:Test,fmtName:"",lName:User,mName:M,nName:"",suffix:"",title:"Mr.",webAccounts:[]}' ) ) 10 | .to.deep.equal( {fName:"Test",fmtName:"",lName:"User",mName:"M",nName:"",suffix:"",title:"Mr.",webAccounts:[]} ); 11 | } ); 12 | it( 'handles keywords with spaces', function() { 13 | expect( JSOX.parse( "[null,null,null, null , null,null ,null]" ) ) 14 | .to.deep.equal( [null,null,null, null , null,null ,null] ); 15 | } ); 16 | 17 | // references which revived deeply in the current stack.... 18 | // node ../tests/data/rawtest.js ./testReferenceRevive.jsox 19 | 20 | } ); 21 | -------------------------------------------------------------------------------- /tests/dateTest.js: -------------------------------------------------------------------------------- 1 | 2 | const JSOX = require('..'); 3 | 4 | console.log( "Date:", JSOX.stringify( new Date() ) ); 5 | const wasDate = JSOX.parse( "2020-11-22T11:08:09.415-08:00" ); 6 | console.log( "Date:", wasDate ); 7 | 8 | //const test = '{TaxId:[{tag:SSN,value:"123-456-7890"}],addresses:[],bankAccounts:[],contact:[],data:ref[],dob:2020-11-21T21:55:05.596-06:00,email:[],fName:Test,fmtName:"",lName:User,mName:M,nName:"",suffix:"",title:"Mr.",webAccounts:[]}'; 9 | //const out = JSOX.parse( test ); 10 | 11 | const jsox = '{a:"",b:[{c:[{d:false}]}],e:"TEST"}'; 12 | console.log(JSOX.stringify(JSOX.parse(jsox))); // prints { a: '', b: '', e: 'TEST' } 13 | //if no field is there it is parsed correctly as array 14 | 15 | const jsox2 = '{a:"",b:[{c:[{d:false}]}]}'; 16 | console.log(JSOX.stringify(JSOX.parse(jsox2))); // prints { a: '', b: [ { c: [Array] } ] } 17 | -------------------------------------------------------------------------------- /test/1.2.106-require.mjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import {JSOX} from "jsox"; 3 | //require( "../lib/require.js" ); 4 | 5 | import {default as config} from './1.2.106-require.jsox' 6 | 7 | describe('Added in 1.2.106 - require(esm)', function () { 8 | it('extends import operator', function() { 9 | expect( config ).to.deep.equal( { 10 | desc: "configuration file to read", 11 | date : new Date( "2021-01-02T00:00:00Z" ), 12 | value:123} 13 | ); 14 | 15 | } ); 16 | 17 | it('allows using require on extension', function () { 18 | return import( "./1.2.106-require.jsox" ).then( newConfig=>{ 19 | //console.log( "GOT:", newConfig ); 20 | expect( newConfig.default ).to.deep.equal( { 21 | desc: "configuration file to read", 22 | date : new Date( "2021-01-02T00:00:00Z" ), 23 | value:123} 24 | ); 25 | } ); 26 | } ); 27 | } ); 28 | -------------------------------------------------------------------------------- /tests/benchmark/bench1a.js: -------------------------------------------------------------------------------- 1 | var JSOX=require("../.." ); 2 | 3 | function runParser( l, p ) { 4 | const s = p.stringify; 5 | const parse = p.parse; 6 | 7 | var n; 8 | var o1 = { a: 123, b:467, c:"1234", d:35.1, e:new Date() }; 9 | var s1; 10 | var start; 11 | var result = { s:0,sn:0,p:0,pn:0}; 12 | 13 | start = Date.now(); 14 | 15 | for( n = 0; ((n%1000)!=999) || ((Date.now()-start) < 5000 ); n++ ) { 16 | s1 = s(o1); 17 | } 18 | console.log( l,"String Did", result.sn =n, "in", result.s =Date.now()-start ); 19 | 20 | return result; 21 | } 22 | 23 | 24 | var x = runParser( "JSOX", JSOX ); 25 | var n = runParser( "JSON", JSON ); 26 | 27 | console.log( x.sn/n.sn); 28 | //console.log( x.pn/n.pn); 29 | console.log( n.sn/x.sn); 30 | //console.log( n.pn/x.pn); 31 | -------------------------------------------------------------------------------- /tests/objectProto/testProto.js: -------------------------------------------------------------------------------- 1 | 2 | const JSOX = require( "../.." ); 3 | 4 | var jsox = ` 5 | cls{ author, title } 6 | cls2{ object,color} 7 | [cls{"bob","book"}, 8 | cls{"tom","moon"}, 9 | cls{"ted","mule"}, 10 | cls2{"apple","red"}, 11 | cls2{"orange","orange"} 12 | ] 13 | `; 14 | 15 | var arr = JSOX.parse( jsox ); 16 | 17 | Object.getPrototypeOf( arr[0] ).toString = function(){ return this.author + " wrote " + this.title }; 18 | Object.getPrototypeOf( arr[3] ).toString = function(){ return this.object + "s are " + this.color }; 19 | 20 | //console.log( "Test:", Object.getPrototypeOf( arr[0] ), Object.getPrototypeOf( Object.getPrototypeOf( arr[0] ) ) ); 21 | 22 | console.log( "object toString():" + {}.toString() ); 23 | console.log( "arr[2].toString(cls):" + arr[2].toString() ); 24 | console.log( "arr[4].toString(cls2):" + arr[3].toString() ); 25 | -------------------------------------------------------------------------------- /tests/stringify/testExternRef.js: -------------------------------------------------------------------------------- 1 | 2 | var JSOX = require( "../.." ) 3 | 4 | function Node() { 5 | this.ID = "abc1567"; 6 | } 7 | 8 | JSOX.registerToFrom( "exref", Node.prototype 9 | , function() { 10 | console.log( "encode object from Object: %s", JSON.stringify(this) ); 11 | return '\"abc1234=\"'; 12 | } 13 | , function() { 14 | console.log( "Resuurect from Array: %s", this ); 15 | return this; 16 | } ); 17 | 18 | JSOX.registerToFrom( "exref2", {ID:undefined} 19 | , function() { 20 | console.log( "encode extref2 from Array: %s", JSON.stringify(this) ); 21 | return '\"azz5534=\"'; 22 | } 23 | , function() { 24 | console.log( "Resuurect from Array:[%s]", this ); 25 | return this; 26 | } ); 27 | 28 | var stringify = JSOX.stringify; 29 | var parse = JSOX.parse; 30 | 31 | var o = { n:new Node(), m:{ ID:"aabbcc123"} }; 32 | console.log( stringify( o ) ); 33 | -------------------------------------------------------------------------------- /test/1.2.121.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | const JSOX = require( ".." ); 4 | 5 | /* 6 | process.on("beforeExit", ()=>{ console.log( "EXITING" ) } ); 7 | process.on("uncaughtException",(a,b)=>{ 8 | console.log( "test", a, b ); 9 | } ); 10 | 11 | function describe(a,b) { return b() }; 12 | function it(a,b) { return b() }; 13 | let threw = null; 14 | function expect(a) { if( "function" === typeof a ) { try { threw = null; a(); } catch(err){threw=err}; } 15 | return ({ to: {deep:{ equal(b) { console.log( "did",a,"=",b); } } 16 | , equal(b) { console.log( "did",a,"=",b); } 17 | , throw(a) {console.log( "Success:error?", threw ) } } }); } 18 | */ 19 | 20 | 21 | describe('Added in 1.2.121', function () { 22 | 23 | it( 'Stringifies "[]" with quotes', function() { 24 | const string = '[]'; 25 | const expects = JSOX.stringify(string); 26 | 27 | expect( expects ).to.equal( '"[]"' ); 28 | 29 | } ); 30 | 31 | } ); 32 | 33 | 34 | -------------------------------------------------------------------------------- /tests/testUnicode.js: -------------------------------------------------------------------------------- 1 | 2 | var JSOX = require( ".." ) 3 | 4 | console.log( "Thing is:", JSOX.stringify( "\ud800" ) ); 5 | 6 | 7 | process.stdin.on('data', processLine ); 8 | 9 | //var line = require( 'fs').readFileSync(0); // STDIN_FILENO = 0 10 | //console.log(stdinBuffer.toString()); 11 | 12 | //process.stdin.pipe(require('split')()).on('data', processLine) 13 | //processLine(line) 14 | 15 | function processLine (line) { 16 | console.log( "LINE:",line ); 17 | line = line.toString( 'utf8' ); 18 | 19 | console.log( "output 1:" ); 20 | var out; 21 | { console.log( out = JSON.stringify(line.split(""))); } 22 | 23 | console.log( "output 2:", line, JSON.parse( out ) ); 24 | { const s = JSON.parse(out).join(""); console.log(s); } 25 | 26 | console.log( "output 3:" ); 27 | { console.log(out = JSOX.stringify(line.split(""))); } 28 | console.log( "output 4:" ); 29 | { const s = JSOX.parse(out).join(""); console.log(s); } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /tests/stringify/testTypeArray.js: -------------------------------------------------------------------------------- 1 | var JSOX = require( "../.." ) 2 | 3 | var ab = new ArrayBuffer(8); 4 | var u8 = new Uint8Array(ab); 5 | for( var n = 0; n < 8; n++ ) u8[n] = "MNOPQURZ".codePointAt(n); 6 | 7 | 8 | console.log( "MNOP=", JSOX.stringify(JSOX.parse( JSOX.stringify({ab:ab}) )) ); 9 | console.log( "MNOP=", JSOX.stringify(JSOX.parse( JSOX.stringify({ab:new Uint8Array(ab)}) )) ); 10 | console.log( "MNOP=", JSOX.stringify(JSOX.parse( JSOX.stringify({ab:new Uint16Array(ab)}) )) ); 11 | console.log( "MNOP=", JSOX.stringify(JSOX.parse( JSOX.stringify({ab:new Uint32Array(ab)}) )) ); 12 | console.log( "MNOP=", JSOX.stringify(JSOX.parse( JSOX.stringify({ab:new Int8Array(ab)}) )) ); 13 | console.log( "MNOP=", JSOX.stringify(JSOX.parse( JSOX.stringify({ab:new Int16Array(ab)}) )) ); 14 | console.log( "MNOP=", JSOX.stringify(JSOX.parse( JSOX.stringify({ab:new Int32Array(ab)}) )) ); 15 | console.log( "MNOP=", JSOX.stringify(JSOX.parse( JSOX.stringify({ab:new Float32Array(ab)}) )) ); 16 | console.log( "MNOP=", JSOX.stringify(JSOX.parse( JSOX.stringify({ab:new Float64Array(ab)}) )) ); 17 | -------------------------------------------------------------------------------- /tests/newTest/testbuf.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var buf = [123,34,111,112,34,58,34,115,116,111,114,101,77,101,115,115,97,103,101,34,44,102,114,111,109,58,34,117,115,101,114,34,44,115,97,108,116,58,48,44,100,101,108,84,105,109,101,58,39,50,48,49,57,45,48,52,45,50,49,84,48,56,58,51,53,58,49,57,46,48,57,54,90,39,44,109,115,103,58,39,81,0,116,125,117,123,109,101,122,71,1,13,6,59,27,54,33,7,35,2,12,0,124,60,7,54,92,39,48,10,23,1,45,27,30,32,17,20,15,4,78,71,99,108,116,122,124,100,93,86,79,86,77,41,16,60,58,7,92,39,31,14,1,4,106,68,99,121,63,94,83,84,108,7,11,115,82,109,78,71,77,71,50,92,34,92,96,110,115,99,124,31,1,94,71,88,79,97,104,21,45,91,76,68,77,32,68,105,119,92,96,89,80,93,100,17,27,42,16,29,14,22,30,15,92,34,41,82,63,47,42,42,6,25,6,13,38,26,56,54,7,92,39,3,28,66,77,105,88,46,46,99,81,74,75,101,7,11,105,73,75,81,82,102,75,102,125,98,45,37,118,120,95,80,82,24,41,89,123,99,69,118,72,91,120,76,46,12,98,97,105,92,92,10,76,101,83,93,32,3,69,80,66,76,0,109,39,125]; 4 | var str = buf.reduce( (s,c)=>s+=String.fromCodePoint(c), '' ); 5 | 6 | var JSOX = require( "../.." ); 7 | 8 | console.log( " Result:", JSOX.parse( str ) ); 9 | -------------------------------------------------------------------------------- /test/1.2.117.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | const JSOX = require( ".." ); 4 | 5 | /* 6 | process.on("beforeExit", ()=>{ console.log( "EXITING" ) } ); 7 | process.on("uncaughtException",(a,b)=>{ 8 | console.log( "test", a, b ); 9 | } ); 10 | 11 | function describe(a,b) { return b() }; 12 | function it(a,b) { return b() }; 13 | let threw = null; 14 | function expect(a) { if( "function" === typeof a ) { try { threw = null; a(); } catch(err){threw=err}; } 15 | return ({ to: {deep:{ equal(b) { console.log( "did",a,"=",b); } } 16 | , equal(b) { console.log( "did",a,"=",b); } 17 | , throw(a) {console.log( "Success:error?", threw ) } } }); } 18 | */ 19 | 20 | 21 | describe('Added in 1.2.117', function () { 22 | 23 | 24 | 25 | it( 'recovers 0 reference', function() { 26 | const string = '[{self:ref[0]}]'; 27 | const expects = JSOX.parse(string); 28 | const recurs = [{self:null}]; 29 | recurs[0].self = recurs[0]; 30 | //console.log( "Expects to not be an error:", expects ); 31 | expect( expects ).to.deep.equal( recurs ); 32 | 33 | } ); 34 | 35 | } ); 36 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | var JSOXwasm = require( "." ); 2 | 3 | 4 | 5 | JSOXwasm.onRuntimeInitialized =()=>{ 6 | //JSOXwasm._initJSOX(); 7 | //console.log( "WASMTHing:", JSOXwasm, JSON.stringify( Object.keys( JSOXwasm), null, "\t" ) ); 8 | 9 | console.log( "JSOX:", JSOXwasm.parse("[1,2,3]") );//Object.keys() ); 10 | // , e:ref[c] 11 | console.log( "JSOX:", JSOXwasm.parse("{a:1,b:2.3,c:'test', d:123n, f:2019-06-02T05:33:22Z}") );//Object.keys() ); 12 | 13 | var start = Date.now(); 14 | var n; 15 | for( n = 0; n < 100000; n++ ){ 16 | JSOXwasm.parse( "[1,2,3,4,5,6,7,8,10]" ); 17 | JSOXwasm.parse( '"one simple string to parse..."' ); 18 | } 19 | var end = Date.now(); 20 | console.log( "%d in %d %d", n, end-start, n /(end-start)); 21 | 22 | var start = Date.now(); 23 | var n; 24 | for( n = 0; n < 100000; n++ ){ 25 | JSON.parse( "[1,2,3,4,5,6,7,8,10]" ); 26 | JSON.parse( '"one simple string to parse..."' ); 27 | } 28 | var end = Date.now(); 29 | console.log( "%d in %d %d", n, end-start, n /(end-start)); 30 | 31 | 32 | } 33 | 34 | JSOXwasm.onRuntimeInitialized(); -------------------------------------------------------------------------------- /test/1.2.122.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSOX = require( ".." ); 3 | 4 | /* 5 | process.on("beforeExit", ()=>{ console.log( "EXITING" ) } ); 6 | process.on("uncaughtException",(a,b)=>{ 7 | console.log( "test", a, b ); 8 | } ); 9 | 10 | function describe(a,b) { return b() }; 11 | function it(a,b) { return b() }; 12 | let threw = null; 13 | function expect(a) { if( "function" === typeof a ) { try { threw = null; a(); } catch(err){threw=err}; } 14 | return ({ to: {deep:{ equal(b) { console.log( "did",a,"=",b); } } 15 | , equal(b) { console.log( "did",a,"=",b); } 16 | , throw(a) {console.log( "Success:error?", threw ) } } }); } 17 | */ 18 | 19 | 20 | describe('Added in 1.2.122', function () { 21 | 22 | it( 'handles keyword at end of object', function() { 23 | const string = '{op:f}'; 24 | const expects = JSOX.parse(string); 25 | 26 | expect( expects ).to.deep.equal( {op:"f"} ); 27 | 28 | } ); 29 | 30 | it( 'handles keyword at end of array', function() { 31 | const string = '[a,f]'; 32 | const expects = JSOX.parse(string); 33 | 34 | expect( expects ).to.deep.equal( ["a","f"] ); 35 | 36 | } ); 37 | 38 | } ); 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /tests/json6StreamTest.js: -------------------------------------------------------------------------------- 1 | 2 | var JSON6 = require( ".." ); 3 | var parser = JSON6.begin( (obj)=>{ 4 | console.log( "Got value:",typeof obj, ":", obj ); 5 | } ); 6 | 7 | parser.write( '"This ' ); 8 | parser.write( 'is a Test"' ); 9 | 10 | parser.write( '[1234,12'); 11 | parser.write( '34,1234]'); 12 | 13 | parser.write( '[123,4'); 14 | parser.write( '56,78'); 15 | parser.write( '9,"abc","de'); 16 | parser.write( 'f","ghi"]'); 17 | 18 | 19 | parser.write( 'true false null undefined NaN Infinity' ); 20 | 21 | parser.write( "1 " ); 22 | parser.write( "123" ); 23 | parser.write( '"1"' ); 24 | 25 | // this requires having a space, otherwise 26 | // '1' becomes a class identifier for this object. 27 | parser.write( ' { a:12' ); 28 | parser.write( '34 }' ); 29 | 30 | parser.write( '{ long'); 31 | parser.write( 'key:1234 }' ); 32 | 33 | parser.write( '{ a:1234 }' ); 34 | console.log( "4 objects..." ); 35 | parser.write( '{ a:1234 }{ b:34 }{c:1}{d:123}' ); 36 | console.log( "got 4 objects?" ); 37 | 38 | try { 39 | parser.write( 'truefalse' ); 40 | } catch(err) { 41 | console.log( "success error", err ); 42 | } 43 | 44 | parser.reset(); 45 | parser.write( '1_234 0x55_33_22_11 0x1234 ' ); 46 | 47 | -------------------------------------------------------------------------------- /test.mjs: -------------------------------------------------------------------------------- 1 | import {JSOX} from "./lib/jsox.mjs"; 2 | const JSOXwasm = JSOX; 3 | 4 | 5 | 6 | JSOXwasm.onRuntimeInitialized =()=>{ 7 | //JSOXwasm._initJSOX(); 8 | //console.log( "WASMTHing:", JSOXwasm, JSON.stringify( Object.keys( JSOXwasm), null, "\t" ) ); 9 | 10 | console.log( "JSOX:", JSOXwasm.parse("[1,2,3]") );//Object.keys() ); 11 | // , e:ref[c] 12 | console.log( "JSOX:", JSOXwasm.parse("{a:1,b:2.3,c:'test', d:123n, f:2019-06-02T05:33:22Z}") );//Object.keys() ); 13 | 14 | var start = Date.now(); 15 | var n; 16 | for( n = 0; n < 100000; n++ ){ 17 | JSOXwasm.parse( "[1,2,3,4,5,6,7,8,10]" ); 18 | JSOXwasm.parse( '"one simple string to parse..."' ); 19 | } 20 | var end = Date.now(); 21 | console.log( "%d in %d %d", n, end-start, n /(end-start)); 22 | 23 | var start = Date.now(); 24 | var n; 25 | for( n = 0; n < 100000; n++ ){ 26 | JSON.parse( "[1,2,3,4,5,6,7,8,10]" ); 27 | JSON.parse( '"one simple string to parse..."' ); 28 | } 29 | var end = Date.now(); 30 | console.log( "%d in %d %d", n, end-start, n /(end-start)); 31 | 32 | 33 | } 34 | 35 | JSOXwasm.onRuntimeInitialized(); -------------------------------------------------------------------------------- /test/1.2.113-DateNS.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSOX = require( "../lib/jsox.js" ); 3 | 4 | describe('Added in 1.2.113 (DateNS)', function () { 5 | const t = JSOX.stringify( new JSOX.DateNS("2022-01-01T00:00:00Z")); 6 | const plus = t.lastIndexOf( "+" ); 7 | const minus = t.lastIndexOf( "-" ); 8 | const Z = t.lastIndexOf( "Z" ); 9 | const pos = ( plus > minus )?(plus>Z)?plus:Z:(minus>Z)?minus:Z; 10 | const tz = t.substr( pos ); 11 | //console.log( "Date functions require a timezone to be known." ); 12 | //return true; 13 | 14 | it( 'handles stringify', function() { 15 | const str = JSOX.stringify( new JSOX.DateNS( "2022-01-01T00:00:00Z", 123 ) ); 16 | if( tz[0] == '-' && tz !== '-00:00' ) 17 | expect( str ).to.match( new RegExp("2021-12-31T\\d*:00:00.000000123.*" ) ); 18 | else 19 | expect( str ).to.match( new RegExp("2022-01-01T\\d*:00:00.000000123.*" ) ); 20 | } ); 21 | 22 | it( 'handles parse', function() { 23 | const val = JSOX.parse( "2022-01-01T00:00:00.000000123Z" ); 24 | const strval = ''+val.toISOString()+val.ns; 25 | expect( strval ).to.equal( "2022-01-01T00:00:00.000Z123" ); 26 | } ); 27 | 28 | }) 29 | 30 | -------------------------------------------------------------------------------- /tests/test_array_subref.js: -------------------------------------------------------------------------------- 1 | const JSOX=require('..' ); 2 | 3 | const a = { 4 | act : {}, 5 | groups:[], 6 | n: [{ 7 | m :[] 8 | }] 9 | } 10 | a.groups.push( a.act ); 11 | a.n[0].m.push(a.n[0]); 12 | 13 | 14 | const b = { 15 | a: [ {}, { 16 | b: [ { c: [] }] 17 | }], 18 | }; 19 | 20 | b.a[1].b[0].c.push( b.a[1].b[0] ); 21 | 22 | console.log( "No Output is success." ); 23 | var out = JSOX.stringify( b, null, " " ); 24 | var decode = JSOX.parse( out ); 25 | var out2 = JSOX.stringify( decode, null, " " ); 26 | 27 | // console.log( "out1:", out ); 28 | if( out !== out2 ) 29 | { 30 | //console.log( "out1:", out ); 31 | console.log( "out1:", decode ); 32 | console.log( "out1.a[1].b:", decode.a[1].b ); 33 | console.log( "out1:", out2 ); 34 | } 35 | 36 | //a.a.act[1].groups[0].activities.push( a.a.act[1] ); 37 | var out = JSOX.stringify( a, null, " " ); 38 | var decode = JSOX.parse( out ); 39 | var out2 = JSOX.stringify( decode, null, " " ); 40 | 41 | // console.log( "out1:", out ); 42 | if( out !== out2 ) 43 | { 44 | //console.log( "out1:", out ); 45 | console.log( "out1:", decode ); 46 | console.log( "out1.a.groups:", decode.groups ); 47 | console.log( "out1:", out2 ); 48 | } 49 | -------------------------------------------------------------------------------- /lib/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | // cli.js 5 | // JSOX command-line interface. 6 | // 7 | // This is pretty minimal for now; just supports compiling files via `-c`. 8 | // TODO More useful functionality, like output path, watch, etc.? 9 | 10 | const FS = require('fs'); 11 | const JSOX = require('./jsox'); 12 | const Path = require('path'); 13 | 14 | const USAGE = [ 15 | 'Usage: jsox -c path/to/file.jsox ...', 16 | 'Compiles JSOX files into sibling JSON files with the same basenames.', 17 | ].join('\n'); 18 | 19 | // if valid, args look like [node, jsox, -c, file1, file2, ...] 20 | const args = process.argv; 21 | 22 | if (args.length < 4 || args[2] !== '-c') { 23 | console.error(USAGE); 24 | process.exit(1); 25 | } 26 | 27 | const cwd = process.cwd(); 28 | const files = args.slice(3); 29 | 30 | // iterate over each file and convert JSOX files to JSON: 31 | files.forEach(function (file) { 32 | let path = Path.resolve(cwd, file); 33 | const basename = Path.basename(path, '.jsox'); 34 | const dirname = Path.dirname(path); 35 | 36 | const jsox = FS.readFileSync(path, 'utf8'); 37 | const obj = JSOX.parse(jsox); 38 | const json = JSON.stringify(obj, null, 4); // 4 spaces; TODO configurable? 39 | 40 | path = Path.join(dirname, basename + '.json'); 41 | FS.writeFileSync(path, json, 'utf8'); 42 | }); 43 | -------------------------------------------------------------------------------- /tests/json6BadTest.js: -------------------------------------------------------------------------------- 1 | 2 | var JSON6 = require( ".." ) 3 | 4 | 5 | var parse = JSON6.parse; 6 | 7 | var o; 8 | try { 9 | o = parse( "{ true:1 }" ); 10 | console.log( "got back:", o ); 11 | } catch( err ) { console.log( "Expected error, unquoted keyword", err.message ); } 12 | 13 | 14 | 15 | try { 16 | o = parse( "{ a b:1 }" ); 17 | console.log( "got back:", o ); 18 | } catch( err ) { console.log( "Expected error, unquoted space in identifier", err.message ); } 19 | 20 | try { 21 | o = parse( "{ a[3], b:1 }" ); 22 | console.log( "got back:", o ); 23 | } catch( err ) { console.log( "Expected error, missing colon?", err.message ); } 24 | 25 | 26 | try { 27 | o = parse( "{ a{c:3}, b:1 }" ); 28 | console.log( "got back:", o ); 29 | } catch( err ) { console.log( "Expected error, missing colon?", err.message ); } 30 | 31 | try { 32 | o = parse( "{ a : no quote }" ); 33 | console.log( "got back:", o ); 34 | } catch( err ) { console.log( "Expected error, string unquoted?", err.message ); } 35 | 36 | try { 37 | o = parse( "a" ); 38 | console.log( "got back:", o ); 39 | } catch( err ) { console.log( "Expected error, string unquoted?", err.message ); } 40 | 41 | try { 42 | o = parse( "{ a : 'no quote' [1] }" ); 43 | console.log( "got back:", o ); 44 | } catch( err ) { console.log( "Expected error, array after string?", err.message ); } 45 | -------------------------------------------------------------------------------- /lib/require.js: -------------------------------------------------------------------------------- 1 | // require.js 2 | // Node.js only: adds a require() hook for .json6 files, just like the native 3 | // hook for .json files. 4 | // 5 | // Usage: 6 | // require('json6/require'); 7 | // require('./foo'); // will check foo.json5 after foo.js, foo.json, etc. 8 | // require('./bar.json6'); 9 | "use strict"; 10 | 11 | const FS = require('fs'); 12 | const JSOX = require('./jsox.min.js').JSOX; 13 | 14 | // Modeled off of (v0.6.18 link; check latest too): 15 | // https://github.com/joyent/node/blob/v0.6.18/lib/module.js#L468-L472 16 | require.extensions['.jsox'] = function (module, filename) { 17 | const content = FS.readFileSync(filename, 'utf8'); 18 | return module.exports = JSOX.parse(content); 19 | }; 20 | 21 | const Module = require('module'); 22 | const zlib = require('zlib'); 23 | 24 | function requireGZ(module,filename) { 25 | const code = zlib.gunzipSync(FS.readFileSync(filename)).toString(); 26 | const mod = new Module(); 27 | 28 | mod._compile(code, filename); 29 | 30 | return mod.exports; 31 | } 32 | 33 | function requireGZx(module,filename) { 34 | const code = zlib.gunzipSync(FS.readFileSync(filename)).toString(); 35 | return module.exports = JSOX.parse(code); 36 | } 37 | 38 | require.extensions['.js.gz'] = requireGZ; 39 | require.extensions['.jsox.gz'] = requireGZx; 40 | 41 | // Use: 42 | //let test = requireGZ('./test.js.gz'); 43 | -------------------------------------------------------------------------------- /json.bnf: -------------------------------------------------------------------------------- 1 | json 2 | element 3 | 4 | value 5 | object 6 | array 7 | string 8 | number 9 | "true" 10 | "false" 11 | "null" 12 | 13 | object 14 | '{' ws '}' 15 | '{' members '}' 16 | 17 | members 18 | member 19 | member ',' members 20 | 21 | member 22 | ws string ws ':' element 23 | 24 | array 25 | '[' ws ']' 26 | '[' elements ']' 27 | 28 | elements 29 | element 30 | element ',' elements 31 | 32 | element 33 | ws value ws 34 | 35 | string 36 | '"' characters '"' 37 | characters 38 | "" 39 | character characters 40 | character 41 | '0020' . '10ffff' - '"' - '\' 42 | '\' escape 43 | escape 44 | '"' 45 | '\' 46 | '/' 47 | 'b' 48 | 'n' 49 | 'r' 50 | 't' 51 | 'u' hex hex hex hex 52 | 53 | hex 54 | digit 55 | 'A' . 'F' 56 | 'a' . 'f' 57 | 58 | number 59 | int frac exp 60 | 61 | int 62 | digit 63 | onenine digits 64 | '-' digit 65 | '-' onenine digits 66 | 67 | digits 68 | digit 69 | digit digits 70 | 71 | digit 72 | '0' 73 | onenine 74 | 75 | onenine 76 | '1' . '9' 77 | 78 | frac 79 | "" 80 | '.' digits 81 | 82 | exp 83 | "" 84 | 'E' sign digits 85 | 'e' sign digits 86 | 87 | sign 88 | "" 89 | '+' 90 | '-' 91 | 92 | ws 93 | "" 94 | '0009' ws 95 | '000a' ws 96 | '000d' ws 97 | '0020' ws 98 | -------------------------------------------------------------------------------- /test/1.2.104-stringify.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSOX = require( ".." ); 3 | 4 | describe('JSOX stringify', function () { 5 | 6 | it('stringifies Infinity', function () { 7 | expect( JSOX.stringify( { d:Infinity } ) ).to.equal( '{d:Infinity}' ); 8 | } ); 9 | 10 | it('stringifies NaN', function () { 11 | expect( JSOX.stringify( { e:NaN } ) ).to.equal( '{e:NaN}' ); 12 | } ); 13 | 14 | it('basically stringifies', function () { 15 | expect( JSOX.stringify( { a:1 16 | , b:"123" 17 | , c:null 18 | , d:Infinity, e:NaN 19 | , f:false 20 | , t:true } ) ) 21 | .to.equal( '{a:1,b:"123",c:null,d:Infinity,e:NaN,f:false,t:true}' ); 22 | } ); 23 | 24 | it('canonically stringifies', function () { 25 | expect( JSOX.stringify( { z:1 26 | , y:"123" 27 | , x:null 28 | , w:Infinity 29 | , v:NaN 30 | , f:false 31 | , '':'' 32 | , get g() { return 0; } 33 | , t:true } ) ) 34 | .to.equal( '{\"\":"",f:false,g:0,t:true,v:NaN,w:Infinity,x:null,y:"123",z:1}' ); 35 | } ); 36 | 37 | it('can skip non-enumerable', function () { 38 | const stringifier = JSOX.stringifier(); 39 | stringifier.ignoreNonEnumerable = true; 40 | const obj = { z:1 41 | , y:"123" 42 | , x:null 43 | , w:Infinity 44 | , v:NaN 45 | , f:false 46 | , t:true }; 47 | Object.defineProperty( obj, "g", { writable:true, value:true } ); 48 | expect( stringifier.stringify( obj ) ) 49 | .to.equal( '{f:false,t:true,v:NaN,w:Infinity,x:null,y:"123",z:1}' ); 50 | } ); 51 | 52 | 53 | } ); 54 | -------------------------------------------------------------------------------- /test/sack-vfs-1.0.1013.mjs: -------------------------------------------------------------------------------- 1 | import {JSOX} from "../lib/jsox.mjs"; 2 | 3 | /* 4 | process.on("beforeExit", ()=>{ console.log( "EXITING" ) } ); 5 | process.on("uncaughtException",(a,b)=>{ 6 | console.log( "test", a, b ); 7 | } ); 8 | 9 | function describe(a,b) { console.log( "doing:", a ); return b() }; 10 | function it(a,b) { console.log( "test:", a ); return b() }; 11 | let threw = null; 12 | function expect(a) { if( "function" === typeof a ) { try { threw = null; a(); } catch(err){threw=err}; } 13 | return ({ to: {deep:{ equal(b) { console.log( "did",a,"=",b); } } 14 | , equal(b) { console.log( "did",a,"=",b); } 15 | , throw(a) {console.log( "Success:error?", threw ) } } }); } 16 | */ 17 | 18 | class MyObject { 19 | abc=123; 20 | //constructor() { console.log( "Created--" ); } 21 | } 22 | 23 | describe('Added in 1.0.1013', function () { 24 | 25 | it( "parser instance parses simple message?", function() { 26 | const parser = JSOX.begin(); 27 | parser.fromJSOX( "O", MyObject ); 28 | const o1 = parser.parse( '{op:worlds}' ); 29 | const o2 = parser.parse( '{op:"world",world:O{name:"My World"}}' ); 30 | const o3 = JSOX.parse( '{op:"world",world:O{name:"My World"}}' ); 31 | //console.log( o1, o2 ); 32 | expect( o1 ).to.deep.equal( {op:"worlds"} ); 33 | const obj = new MyObject(); 34 | obj.name = "My World" 35 | expect( o2 ).to.deep.equal( {op:"world",world:obj} ); 36 | expect( o3 ).to.deep.equal( {op:"world",world:{name:"My World"}} ); 37 | } ); 38 | } ); 39 | 40 | //setTimeout( ()=>{}, 10000 ); -------------------------------------------------------------------------------- /tests/numberTest.js: -------------------------------------------------------------------------------- 1 | 2 | var JSON = require( '..' ); 3 | 4 | var n = .123; 5 | console.log( "typeof( n ) =", typeof n, n ); 6 | 7 | var n = +.123; 8 | console.log( "typeof( n ) =", typeof n, n ); 9 | 10 | var n = -.123; 11 | console.log( "typeof( n ) =", typeof n, n ); 12 | 13 | var n = .123e3; 14 | console.log( "typeof( n ) =", typeof n, n ); 15 | 16 | var n = .123e-3; 17 | console.log( "typeof( n ) =", typeof n, n ); 18 | 19 | var n = 0x123; 20 | console.log( "typeof( n ) =", typeof n, n ); 21 | 22 | console.log( '-------' ); 23 | 24 | var n = JSON.parse( '.123' ); 25 | console.log( "typeof( n ) =", typeof n, n ); 26 | 27 | var n = JSON.parse( '+.123' ); 28 | console.log( "typeof( n ) =", typeof n, n ); 29 | 30 | var n = JSON.parse( '-.123' ); 31 | console.log( "typeof( n ) =", typeof n, n ); 32 | 33 | var n = JSON.parse( '.123e3' ); 34 | console.log( "typeof( n ) =", typeof n, n ); 35 | 36 | var n = JSON.parse( '.123e-3' ); 37 | console.log( "typeof( n ) =", typeof n, n ); 38 | 39 | var n = JSON.parse( '0x123' ); 40 | console.log( "typeof( n ) =", typeof n, n ); 41 | 42 | function failSuccess( string ) { 43 | try { 44 | var n = JSON.parse( string ); 45 | console.log( "typeof( n ) =", typeof n, n ); 46 | } catch(err) { 47 | console.log( "Expected failure :", string, "failure:", err.message ); 48 | } 49 | } 50 | 51 | failSuccess( ".123-45" ); 52 | failSuccess( ".123e2-45" ); 53 | failSuccess( ".123e--45" ); 54 | failSuccess( ".123e+-45" ); 55 | failSuccess( ".123e3-45" ); 56 | failSuccess( ".05x23" ); 57 | failSuccess( "0xx23" ); 58 | failSuccess( "0x23.45" ); 59 | -------------------------------------------------------------------------------- /test/1.2.104-macro-tag.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSOX = require( ".." ); 3 | 4 | 5 | 6 | describe('Added in 1.2.104 Macro Tags', function () { 7 | it( 'handles macro tags', function() { 8 | const object = JSOX.parse( "vec{x,y} [vec{0,0}, vec{1,1}]" ); 9 | //console.log( "object is:", object);//[{0,0},{1,1}] 10 | expect(object).to.deep.equal( [{x:0,y:0},{x:1,y:1}] ); 11 | 12 | } ); 13 | 14 | it( 'handles macro tags (with space)', function() { 15 | //console.log( "This is a false success..." ); 16 | expect( function() { 17 | const object = JSOX.parse( "vec {x,y} [vec{0,0}, vec{1,1}]" ); 18 | } ).to.throw( Error ); 19 | //console.log( "object is:", object);//[{0,0},{1,1}] 20 | //expect(object).to.deep.equal( [{x:0,y:0},{x:1,y:1}] ); 21 | 22 | } ); 23 | 24 | it( 'handles stringifies to macro tags', function() { 25 | const objectType = { face:null, suit:null }; 26 | JSOX.defineClass( "card", objectType ); 27 | 28 | const str = JSOX.stringify( [{face:0,suit:0},{face:1,suit:1}] ) 29 | expect(str).to.equal( "card{face,suit}[card{0,0},card{1,1}]"); 30 | 31 | } ); 32 | 33 | it( 'handles instanced stringifies to macro tags', function() { 34 | const stringifier = JSOX.stringifier(); 35 | const objectType = { face:null, suit:null }; 36 | stringifier.defineClass( "card", objectType ); 37 | 38 | const str = stringifier.stringify( [{face:0,suit:0},{face:1,suit:1}] ) 39 | expect(str).to.equal( "card{face,suit}[card{0,0},card{1,1}]"); 40 | } ); 41 | 42 | 43 | 44 | } ); 45 | -------------------------------------------------------------------------------- /tests/json6StringTest.js: -------------------------------------------------------------------------------- 1 | 2 | const sack = require( ".." ); 3 | const JSON6 = require( ".." );//sack.JSON6; 4 | 5 | var parser = JSON6.begin( (data)=>{ 6 | console.log( "Test 123456 = ", data ); 7 | } ); 8 | //parser.write( "\'\\x31\\062\\u{33}\\u003456\'" ) 9 | //var string = "\'\\x31\\062\\u{33}\\u003456\'"; 10 | //for( var n = 0; n < string.length; n++ ) 11 | // parser.write( string[n] ); 12 | 13 | function test1() { 14 | console.log( "Output1:", JSON6.parse( '"Simple String value"' ) ); 15 | var start = Date.now(); 16 | var n; 17 | for( n = 0; n < 1000000; n++ ) { 18 | JSON6.parse( '"Simple String value"' ); 19 | } 20 | var end = Date.now(); 21 | console.log( "1m in ", end-start ); 22 | 23 | 24 | var start = Date.now(); 25 | var n; 26 | for( n = 0; n < 1000000; n++ ) { 27 | JSON.parse( '"Simple String value"' ); 28 | } 29 | var end = Date.now(); 30 | console.log( "1m in ", end-start ); 31 | 32 | } 33 | 34 | function test2() { 35 | console.log( "Output2:", JSON6.parse( '"Si\\t \\r\\n lue"' ) ); 36 | var start = Date.now(); 37 | var n; 38 | for( n = 0; n < 1000000; n++ ) { 39 | JSON6.parse( '"Si\\t \\r\\n lue"' ); 40 | } 41 | 42 | var end = Date.now(); 43 | console.log( "1m in ", end-start ); 44 | 45 | var start = Date.now(); 46 | var n; 47 | for( n = 0; n < 1000000; n++ ) { 48 | JSON.parse( '"Si\\t \\r\\n lue"' ); 49 | } 50 | 51 | var end = Date.now(); 52 | console.log( "1m in ", end-start ); 53 | 54 | setTimeout( test1, 10 ); 55 | 56 | } 57 | 58 | setTimeout( test2, 10 ); 59 | 60 | 61 | //console.log( "Waiting forever..." ); 62 | //function wait() { setTimeout( wait, 2000 ) } 63 | //wait(); 64 | -------------------------------------------------------------------------------- /test/sack-vfs-1.0.1007-base64.mjs: -------------------------------------------------------------------------------- 1 | import {JSOX} from "jsox"; 2 | /* 3 | process.on("beforeExit", ()=>{ console.log( "EXITING" ) } ); 4 | process.on("uncaughtException",(a,b)=>{ 5 | console.log( "test", a, b ); 6 | } ); 7 | 8 | function describe(a,b) { console.log( "doing:", a ); return b() }; 9 | function it(a,b) { console.log( "test:", a ); return b() }; 10 | let threw = null; 11 | function expect(a) { if( "function" === typeof a ) { try { threw = null; a(); } catch(err){threw=err}; } 12 | return ({ to: {deep:{ equal(b) { console.log( "did",a,"=",b); } } 13 | , equal(b) { console.log( "did",a,"=",b); } 14 | , throw(a) {console.log( "Success:error?", threw ) } } }); } 15 | */ 16 | 17 | describe('Added in 1.0.1007 (base64)', function () { 18 | 19 | 20 | 21 | it( 'Accepts $ and _ for encoding', function() { 22 | //console.log( "Parsed:", JSOX.parse( '{\n\t"a" : "b", "c" : "d" }' ) ) 23 | //console.log( "Parsed:", JSOX.parse( '{\n\t"a" : "b", "c" : "d" }' ) ) 24 | const buf2 = JSOX.parse( '{buf:ab["+/+/"] }' ); 25 | const buf = JSOX.parse( '{buf:ab[$_$_] }' ); 26 | const outbuf = JSOX.stringify( buf ); 27 | //console.log( 'buf:', outbuf, buf, "B", buf2 ); 28 | expect( JSOX.stringify( buf2 ) ) 29 | .to.equal( '{buf:ab[$_$_]}' ); 30 | expect( JSOX.stringify( buf ) ) 31 | .to.equal( '{buf:ab[$_$_]}' ); 32 | 33 | expect( JSOX.parse( '{buf:ab["+/+/"] }' ) ) 34 | .to.deep.equal( buf ); 35 | expect( JSOX.parse( '{buf:ab[$_$_] }' ) ) 36 | .to.deep.equal( buf2 ); 37 | // console.log( "Fail:", obj ); 38 | } ) 39 | } ) 40 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017+ d3x0r (github id) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | ------ 24 | If you make notable improvments/fixes I would appreciate a best effort to share 25 | such changes; or at least share that there might be a possibility of improvement. 26 | There is no penalty if nothing is shared. I attempted to get JSON5 maintainers 27 | to implement the changes before re-implementing, but they were unresponsive. 28 | Besides this implementation is twice the speed, so it benefits a lot from not 29 | being based on their code in the first place. It's only based on the description 30 | of their extensions to original JSON format. -------------------------------------------------------------------------------- /tests/stringify/testArrayStringify.js: -------------------------------------------------------------------------------- 1 | 2 | var JSOX = require( "../.." ) 3 | 4 | var stringify = JSOX.stringify; 5 | var parse = JSOX.parse; 6 | 7 | 8 | var o; 9 | var r, r2, r3; 10 | 11 | r = stringify( [] ); 12 | console.log( "simple Test:", r ); 13 | 14 | r = stringify( o = { op:[], data:[] } ); 15 | console.log( "simple Test:", r ); 16 | 17 | 18 | if( BigInt ) { 19 | r = stringify( o = { a: "simple object", b:3, c:new Date(), d:123n, e:null, f:undefined, g:NaN, h:Infinity, i:-Infinity, j:-0.302, k:new Uint8Array(8) }, null, 3 ); 20 | console.log( "pretty:", o, "=\n", r ); 21 | r = stringify( o = { a: "simple object", b:3, c:new Date(), d:123n, e:null, f:undefined, g:NaN, h:Infinity, i:-Infinity, j:-0.302, k:new Uint8Array(8) } ); 22 | r2 = stringify( parse( r ) ); 23 | if( r != r2 ) 24 | console.log( "3:", r, r2 ); 25 | 26 | r = stringify( [ "simple array", 3, new Date(), 123n, null, undefined, ,NaN, Infinity ] ); 27 | r2 = stringify( parse( r ) ); 28 | if( r != r2 ) 29 | 30 | console.log( "4:", r, r2 ); 31 | 32 | } 33 | 34 | console.log( "validity test..." ); 35 | 36 | r = stringify( o = { "true": "simple object", "false":3, "test extra":new Date(), "This+fails":0, "123":123, 124:123 } ); 37 | //console.log( "will parse:", r ); 38 | r2 = stringify( parse( r ) ); 39 | if( r != r2 ) 40 | console.log( "identTest:", r ); 41 | 42 | 43 | r = stringify( o = { a: "simple object", b:3, c:new Date() } ); 44 | r2 = stringify( parse( r ) ); 45 | if( r != r2 ) 46 | console.log( "1:", r ); 47 | 48 | r = stringify( o = [ "simple array", 3, new Date() ] ); 49 | r2 = stringify( parse( r ) ); 50 | if( r != r2 ) 51 | console.log( "2:", r ); 52 | 53 | 54 | console.log( "Success is no output above this." ); -------------------------------------------------------------------------------- /test/1.2.113-DateNS.mjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import {JSOX} from "jsox"; 3 | 4 | 5 | describe('Added in 1.2.113 (DateNS)', function () { 6 | 7 | const t = JSOX.stringify( new JSOX.DateNS("2022-01-01T00:00:00Z")); 8 | const plus = t.lastIndexOf( "+" ); 9 | const minus = t.lastIndexOf( "-" ); 10 | const Z = t.lastIndexOf( "Z" ); 11 | const pos = ( plus > minus )?(plus>Z)?plus:Z:(minus>Z)?minus:Z; 12 | const tz = t.substr( pos ); 13 | 14 | it( 'handles stringify (with passed UTC timezone)', function() { 15 | const str = JSOX.stringify( new JSOX.DateNS( "2022-01-01T00:00:00Z", 123 ) ); 16 | 17 | if( tz[0] == '-' && tz !== '-00:00' ) 18 | expect( str ).to.match( new RegExp("2021-12-31T\\d*:00:00.000000123.*" ) ); 19 | else 20 | expect( str ).to.match( new RegExp("2022-01-01T\\d*:00:00.000000123.*" ) ); 21 | //expect( str ).to.equal( "2021-12-31T16:00:00.000000123"+tz ); 22 | } ); 23 | 24 | it( 'handles stringify (with timezone offset)', function() { 25 | const str = JSOX.stringify( new JSOX.DateNS( "2022-01-01T00:00:00-05:00", 123 ) ); 26 | if( tz[0] == '-' && tz !== '-00:00' ) 27 | expect( str ).to.match( new RegExp("2021-12-31T\\d*:00:00.000000123.*" ) ); 28 | else 29 | expect( str ).to.match( new RegExp("2022-01-01T\\d*:00:00.000000123.*" ) ); 30 | //expect( str ).to.equal( "2021-12-31T21:00:00.000000123"+tz ); 31 | } ); 32 | 33 | it( 'handles parse', function() { 34 | const val = JSOX.parse( "2022-01-01T00:00:00.000000123Z" ); 35 | const strval = ''+val.toISOString()+val.ns; 36 | expect( strval ).to.equal( "2022-01-01T00:00:00.000Z123" ); 37 | } ); 38 | 39 | }) 40 | 41 | -------------------------------------------------------------------------------- /tests/stringify/testStringify.js: -------------------------------------------------------------------------------- 1 | 2 | var JSOX = require( "../.." ) 3 | 4 | var stringify = JSOX.stringify; 5 | var parse = JSOX.parse; 6 | 7 | 8 | var o; 9 | var r, r2, r3; 10 | 11 | r = stringify( o = { op:"Storage" } ); 12 | console.log( "simple Test:", r ); 13 | 14 | r = stringify( o = { op:"Storage", data:[] } ); 15 | console.log( "simple Test:", r ); 16 | 17 | 18 | if( BigInt ) { 19 | r = stringify( o = { a: "simple object", b:3, c:new Date(), d:123n, e:null, f:undefined, g:NaN, h:Infinity, i:-Infinity, j:-0.302, k:new Uint8Array(8) }, null, 3 ); 20 | console.log( "pretty:", o, "=\n", r ); 21 | r = stringify( o = { a: "simple object", b:3, c:new Date(), d:123n, e:null, f:undefined, g:NaN, h:Infinity, i:-Infinity, j:-0.302, k:new Uint8Array(8) } ); 22 | r2 = stringify( parse( r ) ); 23 | if( r != r2 ) 24 | console.log( "3:", r, r2 ); 25 | 26 | r = stringify( [ "simple array", 3, new Date(), 123n, null, undefined, ,NaN, Infinity ] ); 27 | r2 = stringify( parse( r ) ); 28 | if( r != r2 ) 29 | 30 | console.log( "4:", r, r2 ); 31 | 32 | } 33 | 34 | console.log( "validity test..." ); 35 | 36 | r = stringify( o = { "true": "simple object", "false":3, "test extra":new Date(), "This+fails":0, "123":123, 124:123 } ); 37 | //console.log( "will parse:", r ); 38 | r2 = stringify( parse( r ) ); 39 | if( r != r2 ) 40 | console.log( "identTest:", r ); 41 | 42 | 43 | r = stringify( o = { a: "simple object", b:3, c:new Date() } ); 44 | r2 = stringify( parse( r ) ); 45 | if( r != r2 ) 46 | console.log( "1:", r ); 47 | 48 | r = stringify( o = [ "simple array", 3, new Date() ] ); 49 | r2 = stringify( parse( r ) ); 50 | if( r != r2 ) 51 | console.log( "2:", r ); 52 | 53 | 54 | console.log( "Success is no output above this." ); -------------------------------------------------------------------------------- /tests/testRef3.js: -------------------------------------------------------------------------------- 1 | 2 | //import {JSOX} from "../lib/jsox.mjs" ; 3 | const JSOX = require('..'); 4 | 5 | 6 | const worldStr = `{op:world,world:{bodies:[],lines:[],name:null, 7 | names:[{flags:{vertical:false},name:Default}], 8 | sectors:[ 9 | {id:0,name:null,r:{n:v3{x:0,y:1,z:0},o:v3{x:0,y:0,z:0}}, 10 | texture:{flags:{color:true},name:ref["world","names",0]}, 11 | wall:{end:{end:{end:ref["world","sectors",0,"wall","end"],end_at_end:true,id:3,into:null, 12 | line:{from:-5,r:{n:v3{x:0,y:1,z:0},o:v3{x:5,y:0,z:0}},to:5},name:null, 13 | start:{end:ref["world","sectors",0,"wall","end","end"],end_at_end:false,id:2,into:null, 14 | line:{from:-5,r:{n:v3{x:1,y:0,z:0},o:v3{x:0,y:-5,z:0}},to:5},name:null, 15 | start:ref["world","sectors",0,"wall"],start_at_end:false},start_at_end:true},end_at_end:false,id:1,into:null, 16 | line:{from:-5,r:{n:v3{x:1,y:0,z:0},o:v3{x:0,y:5,z:0}},to:5},name:null, 17 | start:ref["world","sectors",0,"wall"],start_at_end:true},end_at_end:false,id:0,into:null, 18 | line:{from:-5,r:{n:v3{x:0,y:1,z:0},o:v3{x:-5,y:0,z:0}},to:5},name:null, 19 | start:ref["world","sectors",0,"wall","end","end","start"],start_at_end:false} 20 | } 21 | ], 22 | textures:[ref["world","sectors",0,"texture"]], 23 | walls:[ref["world","sectors",0,"wall"],ref["world","sectors",0,"wall","end"],ref["world","sectors",0,"wall","end","end","start"],ref["world","sectors",0,"wall","end","end"]]}}` 24 | const worldObj = JSOX.parse( worldStr ); 25 | console.log( "GOT:", worldObj ); 26 | //console.log( "GOT:", worldObj.world.walls ); 27 | for( let wall of worldObj.world.walls ) { 28 | if( wall.start instanceof Array ) { 29 | console.log( "PING" ); 30 | console.log( "GOT:", wall ); 31 | } 32 | if( wall.end instanceof Array ) { 33 | console.log( "PING2" ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /test/1.2.102.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | const JSOX = require( ".." ); 4 | 5 | describe('Added in 1.2.102', function () { 6 | 7 | 8 | 9 | it( 'handles ref revivals', function() { 10 | const w1 = {end:null,start:null}; 11 | const w2 = {end:null,start:null}; 12 | const w3 = {end:null,start:null}; 13 | const w4 = {end:null,start:null}; 14 | w1.start = w2; 15 | w1.end = w3; 16 | w2.start = w1; 17 | w2.end = w4; 18 | w3.start = w1; 19 | w3.end = w4; 20 | w4.start = w2; 21 | w4.end = w3; 22 | 23 | // {op:"move",walls:[{end:{end:{end:ref["walls",0,"end"],start:{end:ref["walls",0,"end","end"],start:ref["walls",0]}},start:ref["walls",0]},start:ref["walls",0,"end","end","start"]},ref["walls",0,"end","end","start"],ref["walls",0,"end"],ref["walls",0,"end","end"]]} 24 | // {op:"move",walls:[{end:{end:{end:ref["walls",0,"end"],start:{end:ref["walls",0,"end","end"],start:ref["walls",0,"end","end","start"]}},start:ref["walls",0,"end"]},start:ref["walls"]},ref["walls",0,"end","end","start"],ref["walls",0,"end"],ref["walls",0,"end","end"]]} 25 | const o = {op:"move", walls: [w1,w2,w3,w4] } 26 | const str = JSOX.stringify( o ); 27 | 28 | const obj = JSOX.parse( str ); 29 | if( obj.walls[0].start === obj.walls[1] && 30 | obj.walls[0].end === obj.walls[2] && 31 | obj.walls[3].start === obj.walls[1] && 32 | obj.walls[3].end === obj.walls[2] && 33 | obj.walls[1].start === obj.walls[0] && 34 | obj.walls[1].end === obj.walls[3] && 35 | obj.walls[2].start === obj.walls[0] && 36 | obj.walls[1].end === obj.walls[3] ) { 37 | /* success */; 38 | } else { 39 | console.log( "Failed TEST:", obj, o ); 40 | throw new Error( "Object Mis-Match") ; 41 | } 42 | const str2 = JSOX.stringify( obj ); 43 | //console.log( "got:", str ); 44 | expect( str2 ).to.equal( str2 ); 45 | 46 | } ); 47 | 48 | } ); 49 | -------------------------------------------------------------------------------- /test/1.2.102.mjs: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | import {JSOX} from "jsox"; 4 | 5 | describe('Added in 1.2.102(module)', function () { 6 | 7 | 8 | 9 | it( 'handles ref revivals', function() { 10 | const w1 = {end:null,start:null}; 11 | const w2 = {end:null,start:null}; 12 | const w3 = {end:null,start:null}; 13 | const w4 = {end:null,start:null}; 14 | w1.start = w2; 15 | w1.end = w3; 16 | w2.start = w1; 17 | w2.end = w4; 18 | w3.start = w1; 19 | w3.end = w4; 20 | w4.start = w2; 21 | w4.end = w3; 22 | 23 | // {op:"move",walls:[{end:{end:{end:ref["walls",0,"end"],start:{end:ref["walls",0,"end","end"],start:ref["walls",0]}},start:ref["walls",0]},start:ref["walls",0,"end","end","start"]},ref["walls",0,"end","end","start"],ref["walls",0,"end"],ref["walls",0,"end","end"]]} 24 | // {op:"move",walls:[{end:{end:{end:ref["walls",0,"end"],start:{end:ref["walls",0,"end","end"],start:ref["walls",0,"end","end","start"]}},start:ref["walls",0,"end"]},start:ref["walls"]},ref["walls",0,"end","end","start"],ref["walls",0,"end"],ref["walls",0,"end","end"]]} 25 | const o = {op:"move", walls: [w1,w2,w3,w4] } 26 | const str = JSOX.stringify( o ); 27 | 28 | const obj = JSOX.parse( str ); 29 | if( obj.walls[0].start === obj.walls[1] && 30 | obj.walls[0].end === obj.walls[2] && 31 | obj.walls[3].start === obj.walls[1] && 32 | obj.walls[3].end === obj.walls[2] && 33 | obj.walls[1].start === obj.walls[0] && 34 | obj.walls[1].end === obj.walls[3] && 35 | obj.walls[2].start === obj.walls[0] && 36 | obj.walls[1].end === obj.walls[3] ) { 37 | /* success */; 38 | } else { 39 | console.log( "Failed TEST:", obj, o ); 40 | throw new Error( "Object Mis-Match") ; 41 | } 42 | const str2 = JSOX.stringify( obj ); 43 | //console.log( "got:", str ); 44 | expect( str2 ).to.equal( str2 ); 45 | 46 | } ); 47 | 48 | } ); 49 | -------------------------------------------------------------------------------- /test/benchmarks/json6StringTest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // var sack = require( "../../" ); 4 | const JSON6 = require( "../../" ); // sack.JSON6; 5 | 6 | /* 7 | var parser = JSON6.begin( function (data) { 8 | console.log( "Test 123456 = ", data ); 9 | } ); 10 | */ 11 | // parser.write( "\'\\x31\\062\\u{33}\\u003456\'" ) 12 | // var string = "\'\\x31\\062\\u{33}\\u003456\'"; 13 | // for( var n = 0; n < string.length; n++ ) 14 | // parser.write( string[n] ); 15 | 16 | describe('String tests', function () { 17 | this.timeout(7000); 18 | it('Simple string', function () { 19 | console.log( "Output1:", JSON6.parse( '"Simple String value"' ) ); 20 | let start = Date.now(); 21 | let result; 22 | for( let n = 0; n < 1000000; n++ ) { 23 | result = JSON6.parse( '"Simple String value"' ); 24 | } 25 | let end = Date.now(); 26 | console.log( "1m in ", end - start ); 27 | expect(result).to.equal('Simple String value'); 28 | 29 | 30 | start = Date.now(); 31 | for( let n = 0; n < 1000000; n++ ) { 32 | result = JSON.parse( '"Simple String value"' ); 33 | } 34 | end = Date.now(); 35 | console.log( "1m in ", end - start ); 36 | expect(result).to.equal('Simple String value'); 37 | }); 38 | it('String with whitespace escapes', function () { 39 | console.log( "Output2:", JSON6.parse( '"Si\\t \\r\\n lue"' ) ); 40 | let start = Date.now(); 41 | for( let n = 0; n < 1000000; n++ ) { 42 | JSON6.parse( '"Si\\t \\r\\n lue"' ); 43 | } 44 | 45 | let end = Date.now(); 46 | console.log( "1m in ", end - start ); 47 | 48 | start = Date.now(); 49 | for( let n = 0; n < 1000000; n++ ) { 50 | JSON.parse( '"Si\\t \\r\\n lue"' ); 51 | } 52 | 53 | end = Date.now(); 54 | console.log( "1m in ", end-start ); 55 | }); 56 | }); 57 | 58 | // console.log( "Waiting forever..." ); 59 | // function wait() { setTimeout( wait, 2000 ) } 60 | // wait(); 61 | -------------------------------------------------------------------------------- /tests/testNumberConvert.js: -------------------------------------------------------------------------------- 1 | // this is a benchmark of number conversion methods and applications of negative or positibe 2 | console.log( "ES Number Conversion Benchmark" ) 3 | 4 | function test() 5 | { 6 | 7 | var negative = true 8 | 9 | const val = { string : "1234", negative : false }; 10 | 11 | 12 | 13 | start = Date.now(); 14 | for( var m = 0; m < 5000; m++ ) {val.negative = m&1; 15 | for( var n = 0; n < 100000; n++ ) 16 | //negative?-Number( "1234" ):Number("1234"); 17 | val.negative?-Number(val.string):Number(val.string); 18 | } 19 | console.log( "took:", Date.now() - start ); 20 | 21 | var start = Date.now(); 22 | 23 | for( var m = 0; m < 5000; m++ ) { val.negative = m&1; 24 | for( var n = 0; n < 100000; n++ ) 25 | (val.negative?-1:1) * Number(val.string); 26 | //Number("1234") * (negative?-1:1); 27 | } 28 | console.log( "took:", Date.now() - start ); 29 | 30 | 31 | 32 | var start = Date.now(); 33 | 34 | for( var m = 0; m < 5000; m++ ) { val.negative = m&1; 35 | for( var n = 0; n < 100000; n++ ) 36 | Number(val.string) * (val.negative?-1:1); 37 | //Number("1234") * (negative?-1:1); 38 | } 39 | console.log( "took:", Date.now() - start ); 40 | 41 | 42 | 43 | 44 | start = Date.now(); 45 | for( var m = 0; m < 5000; m++ ) {negative = m&1; 46 | for( var n = 0; n < 100000; n++ ) 47 | //negative?-Number( "1234" ):Number("1234"); 48 | negative?-Number(val.string):Number(val.string); 49 | } 50 | console.log( "took:", Date.now() - start ); 51 | 52 | 53 | var start = Date.now(); 54 | 55 | for( var m = 0; m < 5000; m++ ) { negative = m&1; 56 | for( var n = 0; n < 100000; n++ ) 57 | Number(val.string) * (negative?-1:1); 58 | //Number("1234") * (negative?-1:1); 59 | } 60 | console.log( "took:", Date.now() - start ); 61 | 62 | 63 | var start = Date.now(); 64 | 65 | for( var m = 0; m < 5000; m++ ) { negative = m&1; 66 | for( var n = 0; n < 100000; n++ ) 67 | (negative?-1:1) * Number(val.string); 68 | //Number("1234") * (negative?-1:1); 69 | } 70 | console.log( "took:", Date.now() - start ); 71 | } 72 | 73 | test(); -------------------------------------------------------------------------------- /test/1.2.103.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSOX = require( ".." ); 3 | 4 | /* 5 | process.on("beforeExit", ()=>{ console.log( "EXITING" ) } ); 6 | process.on("uncaughtException",(a,b)=>{ 7 | console.log( "test", a, b ); 8 | } ); 9 | 10 | function describe(a,b) { return b() }; 11 | function it(a,b) { return b() }; 12 | let threw = null; 13 | function expect(a) { if( "function" === typeof a ) { try { threw = null; a(); } catch(err){threw=err}; } 14 | return ({ to: {deep:{ equal(b) { console.log( "did",a,"=",b); } } 15 | , equal(b) { console.log( "did",a,"=",b); } 16 | , throw(a) {console.log( "Success:error?", threw ) } } }); } 17 | */ 18 | 19 | 20 | describe('Added in 1.2.103', function () { 21 | 22 | 23 | 24 | it( 'handles fromJSOX per field', function() { 25 | 26 | const content = 'O{a:123,b:345,c:[5,6,7]}' 27 | const processed = []; 28 | const array = []; 29 | class O { 30 | a = 0; 31 | b = 0; 32 | c = array; 33 | constructor() { 34 | processed.push( "Constructed O" ); 35 | } 36 | } 37 | function fromJSOX( field, val ) { 38 | if( field ) { 39 | processed.push( [field, JSON.stringify(val)].join() ); 40 | if( field === "c" ) 41 | return this.c; 42 | else 43 | return val; 44 | } else { 45 | processed.push( "Final revive" ); 46 | this.c.push(8); 47 | return this; 48 | } 49 | 50 | } 51 | JSOX.fromJSOX( "O", O, fromJSOX ); 52 | const object = JSOX.parse( content ); 53 | 54 | //console.log( "Process:\n", processed.join("\n") ); 55 | 56 | expect( processed.join("\n") ).to.equal( `Constructed O 57 | a,123 58 | b,345 59 | c,[] 60 | Final revive` ); 61 | expect( object ).to.deep.equal( { a:123,b:345,c:[5,6,7,8] } ); 62 | 63 | } ); 64 | 65 | } ); 66 | -------------------------------------------------------------------------------- /tests/testNumberConvertPlus.js: -------------------------------------------------------------------------------- 1 | // this is a benchmark of number conversion methods and applications of negative or positibe 2 | console.log( "ES Number Conversion Benchmark" ) 3 | 4 | function test() 5 | { 6 | 7 | var negative = true 8 | 9 | const val = { string : "1234", negative : false }; 10 | 11 | console.log( "typeof:", typeof +val.string ); 12 | 13 | start = Date.now(); 14 | for( var m = 0; m < 5000; m++ ) {val.negative = m&1; 15 | for( var n = 0; n < 100000; n++ ) 16 | //negative?-Number( "1234" ):Number("1234"); 17 | val.negative?-(+val.string):(+val.string); 18 | } 19 | console.log( "took:", Date.now() - start ); 20 | 21 | var start = Date.now(); 22 | 23 | for( var m = 0; m < 5000; m++ ) { val.negative = m&1; 24 | for( var n = 0; n < 100000; n++ ) 25 | (val.negative?-1:1) * (+val.string); 26 | //Number("1234") * (negative?-1:1); 27 | } 28 | console.log( "took:", Date.now() - start ); 29 | 30 | 31 | 32 | var start = Date.now(); 33 | 34 | for( var m = 0; m < 5000; m++ ) { val.negative = m&1; 35 | for( var n = 0; n < 100000; n++ ) 36 | (+val.string) * (val.negative?-1:1); 37 | //Number("1234") * (negative?-1:1); 38 | } 39 | console.log( "took:", Date.now() - start ); 40 | 41 | 42 | 43 | 44 | start = Date.now(); 45 | for( var m = 0; m < 5000; m++ ) {negative = m&1; 46 | for( var n = 0; n < 100000; n++ ) 47 | //negative?-Number( "1234" ):Number("1234"); 48 | negative?-(+val.string):(+val.string); 49 | } 50 | console.log( "took:", Date.now() - start ); 51 | 52 | 53 | var start = Date.now(); 54 | 55 | for( var m = 0; m < 5000; m++ ) { negative = m&1; 56 | for( var n = 0; n < 100000; n++ ) 57 | (+val.string) * (negative?-1:1); 58 | //Number("1234") * (negative?-1:1); 59 | } 60 | console.log( "took:", Date.now() - start ); 61 | 62 | 63 | var start = Date.now(); 64 | 65 | for( var m = 0; m < 5000; m++ ) { negative = m&1; 66 | for( var n = 0; n < 100000; n++ ) 67 | (negative?-1:1) * Number(+val.string); 68 | //Number("1234") * (negative?-1:1); 69 | } 70 | console.log( "took:", Date.now() - start ); 71 | } 72 | 73 | test(); -------------------------------------------------------------------------------- /test/json6TestObjectArray.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSON6 = require('..'); 3 | 4 | describe('Objects and arrays', function () { 5 | it('Simple array with number', function () { 6 | const result = JSON6.parse( "[1234]" ); 7 | expect(result).to.deep.equal([1234]); 8 | }); 9 | it('Simple nested array with number', function () { 10 | const result = JSON6.parse( "[1,[2,[3,[4,5]]]]" ); 11 | expect(result).to.deep.equal([1, [2, [3, [4, 5]]]]); 12 | }); 13 | it('Array of objects', function () { 14 | const d = '[ {a: "", b: ""}, {a: "", b: ""} ]'; 15 | const result = JSON6.parse( d ); 16 | expect(result).to.deep.equal([ {a: "", b: ""}, {a: "", b: ""} ]); 17 | }); 18 | it('Array with various types', function () { 19 | const d = '[true, false, -NaN, NaN, -Infinity, Infinity, undefined]'; 20 | const result = JSON6.parse( d ); 21 | expect(result).to.deep.equal([ 22 | true, false, -NaN, NaN, -Infinity, Infinity, undefined 23 | ]); 24 | }); 25 | it('Object with various types', function () { 26 | const d = '{a: true, b: false, c: -NaN, d: NaN, e: -Infinity, f: Infinity, g: undefined, h: null}'; 27 | const result = JSON6.parse( d ); 28 | expect(result).to.deep.equal({ 29 | a: true, b: false, c: -NaN, d: NaN, e: -Infinity, f: Infinity, g: undefined, h: null 30 | }); 31 | }); 32 | it('Array with empty object', function () { 33 | const d = '[{}]'; 34 | const result = JSON6.parse( d ); 35 | expect(result).to.deep.equal([ 36 | {} 37 | ]); 38 | }); 39 | it('Array of objects and array', function () { 40 | const d = '[ {a: "", b: ""}, [1,2], {a: "", b: ""} ]'; 41 | const result = JSON6.parse( d ); 42 | expect(result).to.deep.equal([ {a: "", b: ""}, [1, 2], {a: "", b: ""} ]); 43 | }); 44 | it('Object with child objects and arrays', function () { 45 | const d = '{ a:{a: "", b: ""}, b:[{d:"",e:""},{f:"",g:""}], c:{a: "", b: ""} }'; 46 | const result = JSON6.parse( d ); 47 | expect(result).to.deep.equal({ 48 | a: {a: "", b: ""}, b: [{d:"",e:""}, {f:"",g:""}], c: {a: "", b: ""} 49 | }); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /test/numberTest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSON = require( '..' ); 3 | 4 | describe('Numbers', function () { 5 | it('Decimal', function () { 6 | const n = .123; 7 | const result = JSON.parse( '.123' ); 8 | expect(result).to.equal(n); 9 | }); 10 | it('Positive decimal', function () { 11 | const n = +.123; 12 | const result = JSON.parse( '+.123' ); 13 | expect(result).to.equal(n); 14 | }); 15 | 16 | it('Negative decimal', function () { 17 | const n = -.123; 18 | const result = JSON.parse( '-.123' ); 19 | expect(result).to.equal(n); 20 | }); 21 | 22 | it('Decimal with scientific notation', function () { 23 | const n = .123e3; 24 | const result = JSON.parse( '.123e3' ); 25 | expect(result).to.equal(n); 26 | }); 27 | 28 | it('Decimal ending prematurely (throws)', function () { 29 | expect(function () { 30 | JSON.parse( '14g' ); 31 | }).to.throw(Error,/fault while parsing number|Extra data/); 32 | }); 33 | 34 | it('Decimal with bad scientific notation (throws)', function () { 35 | expect(function () { 36 | JSON.parse( '1ee' ); 37 | }).to.throw(Error); 38 | }); 39 | 40 | it('Decimal with positive scientific notation', function () { 41 | const n = .123e+3; 42 | const result = JSON.parse( '.123e+3' ); 43 | expect(result).to.equal(n); 44 | }); 45 | 46 | it('Decimal with negative scientific notation', function () { 47 | const n = .123e-3; 48 | const result = JSON.parse( '.123e-3' ); 49 | expect(result).to.equal(n); 50 | }); 51 | 52 | it('Hexadecimal', function () { 53 | const n = 0x123; 54 | const result = JSON.parse( '0x123' ); 55 | expect(result).to.equal(n); 56 | }); 57 | 58 | function failSuccess( string ) { 59 | it('Fails with "' + string + '"', function () { 60 | expect(function () { 61 | const result = JSON.parse( string ); 62 | console.log( "typeof( result ) =", typeof result, result ); 63 | }).to.throw(Error); 64 | }); 65 | } 66 | 67 | failSuccess( ".123-45" ); 68 | failSuccess( ".123e2-45" ); 69 | failSuccess( ".123e--45" ); 70 | failSuccess( ".123e+-45" ); 71 | failSuccess( ".123e3-45" ); 72 | failSuccess( ".05x23" ); 73 | failSuccess( "0xx23" ); 74 | failSuccess( "0x23.45" ); 75 | }); 76 | -------------------------------------------------------------------------------- /test/1.2.108-fromJSOX.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | //const SACK=require("../.." ); 3 | //const JSOX = SACK.JSOX; 4 | const JSOX = require( ".." ); 5 | 6 | /* 7 | process.on("beforeExit", ()=>{ console.log( "EXITING" ) } ); 8 | process.on("uncaughtException",(a,b)=>{ 9 | console.log( "test", a, b ); 10 | } ); 11 | 12 | function describe(a,b) { console.log( "doing:", a ); return b() }; 13 | function it(a,b) { console.log( "test:", a ); return b() }; 14 | let threw = null; 15 | function expect(a) { if( "function" === typeof a ) { try { threw = null; a(); } catch(err){threw=err}; } 16 | return ({ to: {deep:{ equal(b) { console.log( "did",a,"=",b); } } 17 | , equal(b) { console.log( "did",a,"=",b); } 18 | , throw(a) {console.log( "Success:error?", threw ) } } }); } 19 | */ 20 | 21 | 22 | describe('Added in 1.2.108 (fromJSOX)', function () { 23 | 24 | 25 | 26 | it( 'handles fromJSOX per field', function() { 27 | JSOX.reset(); 28 | const content = 'O{a:123,b:345,c:[5,6,7]}' 29 | const processed = []; 30 | const array = []; 31 | class O { 32 | a = 0; 33 | b = 0; 34 | c = array; 35 | constructor() { 36 | processed.push( "Constructed O" ); 37 | } 38 | } 39 | function fromJSOX( field, val ) { 40 | if( field ) { 41 | processed.push( [field, JSON.stringify(val)].join() ); 42 | if( field === "c" ) 43 | return this.c; 44 | else 45 | return val; 46 | } else { 47 | processed.push( "Final revive" ); 48 | this.c.push(8); 49 | return this; 50 | } 51 | 52 | } 53 | JSOX.fromJSOX( "O", O, fromJSOX ); 54 | const object = JSOX.parse( content ); 55 | 56 | console.log( "Process:\n", processed.join("\n") ); 57 | 58 | expect( processed.join("\n") ).to.equal( `Constructed O 59 | a,123 60 | b,345 61 | c,[] 62 | Final revive` ); 63 | expect( object ).to.deep.equal( { a:123,b:345,c:[5,6,7,8] } ); 64 | 65 | } ); 66 | 67 | } ); 68 | -------------------------------------------------------------------------------- /tests/data/test.js: -------------------------------------------------------------------------------- 1 | const JSOX = require( "../.." ); 2 | 3 | var FS = require('fs'); 4 | 5 | //console.log( "Magic?", JSOX.stringify(global,null,3)); 6 | 7 | function stringTest(init) { 8 | var _private = init; 9 | Object.assign( this, { 10 | set Value(val) { 11 | _private = val; 12 | }, 13 | get Value() { 14 | return _private; 15 | } 16 | 17 | }); 18 | } 19 | stringTest.prototype.toString = function() { 20 | return '"' + this.Value + '"'; 21 | } 22 | 23 | JSOX.fromJSOX( "stringTest", null, function() { 24 | console.log( "Resuurect from String:[%s]", this ); 25 | return new stringTest( this ); 26 | } ); 27 | 28 | JSOX.toJSOX( "stringTest", stringTest.prototype, stringTest.prototype.toString ); 29 | 30 | JSOX.fromJSOX( "arrayTest", null, function() { 31 | console.log( "Resuurect from Array:[%s]", this ); 32 | return this; 33 | } ); 34 | JSOX.fromJSOX( "objctTest", null, function() { 35 | console.log( "Resuurect from Object:[%s]", this ); 36 | return this; 37 | } ); 38 | 39 | function Color(init) { 40 | if( init ) { 41 | var c = Number(init ); 42 | this.r = ( c / 0x10000 ) &0xFF; 43 | this.g = ( c / 0x100 ) &0xFF; 44 | this.b = ( c / 0x1 ) &0xFF; 45 | } else { 46 | this.r=1; 47 | this.g=2; 48 | this.b=3; 49 | } 50 | this.toString = function() { return '"' + (this.r*0x10000 + this.g*0x100 + this.b) + '"' } 51 | } 52 | 53 | JSOX.addType( "color", Color 54 | , function() { console.log( "calling tojsox?", this ); return this.toString(); } 55 | , function() { 56 | console.log( "Resurrect from String:[%s]", this ); 57 | return new Color(this); 58 | } 59 | ); 60 | 61 | 62 | // Modeled off of (v0.6.18 link; check latest too): 63 | // https://github.com/joyent/node/blob/v0.6.18/lib/module.js#L468-L472 64 | require.extensions['.jsox'] = function (module, filename) { 65 | var content = FS.readFileSync(filename, 'utf8'); 66 | module.exports = JSOX.parse(content); 67 | }; 68 | 69 | for( var n = 2; n < process.argv.length; n++ ) { 70 | var object = require( process.argv[n] ); 71 | console.log( "OUT:", process.argv[n], object ); 72 | console.log( "ENC:", JSOX.stringify( object ) ); 73 | console.log( "ENC:", JSOX.stringify( object, null, 3 ) ); 74 | } 75 | 76 | 77 | -------------------------------------------------------------------------------- /tests/benchmark/bench1.js: -------------------------------------------------------------------------------- 1 | var JSOX=require("../../lib/jsox.js" ); 2 | var JSON5 3 | try { 4 | JSON5=require("json5" ); 5 | }catch(err){} 6 | var JSON6; 7 | try { 8 | JSON6=require("json6" ); 9 | }catch(err){} 10 | //var JSOX=require("../../lib/jsox.es6.pretty.js" ); 11 | var sf = JSOX.stringifier(); 12 | 13 | function runParser( l, p ) { 14 | const s = p === JSOX?sf.stringify:p.stringify; 15 | const parse = p.parse; 16 | 17 | var n; 18 | var o1 = { a: 123, b:467, c:"1234", d:35.1, e:new Date() }; 19 | var s1; 20 | var start; 21 | var result = { s:0,sn:0,p:0,pn:0}; 22 | 23 | start = Date.now(); 24 | 25 | for( n = 0; ((n%3000)!=0) || ((Date.now()-start) < 2000 ); n++ ) { 26 | s1 = s(o1); 27 | } 28 | console.log( l,"String Did", result.sn =n, "in", result.s =Date.now()-start, s1 ); 29 | 30 | start = Date.now(); 31 | for( n = 0; ((n%3000)!=0) || ((Date.now()-start) < 2000 ); n++ ) { 32 | parse(s1); 33 | } 34 | console.log( l,"Parse Did", result.pn =n, "in", result.p =Date.now()-start ); 35 | return result; 36 | } 37 | 38 | 39 | var x = runParser( "JSOX", JSOX ); 40 | var n = runParser( "JSON", JSON ); 41 | if( JSON5 ) 42 | var n5 = runParser( "JSON5", JSON5 ); 43 | if( JSON6 ) 44 | var n6 = runParser( "JSON5", JSON6 ); 45 | 46 | console.log( "Node JSON v JSOX" ); 47 | console.log( "stringify", n.sn/x.sn); 48 | console.log( "parse ", n.pn/x.pn); 49 | 50 | if( JSON5 ) { 51 | console.log( "Node JSON v JSON5" ); 52 | console.log( "stringify", n.sn/n5.sn); 53 | console.log( "parse ", n.pn/n5.pn); 54 | } 55 | 56 | if( JSON6 ) { 57 | console.log( "Node JSON v JSON6" ); 58 | console.log( "stringify", n.sn/n6.sn); 59 | console.log( "parse ", n.pn/n6.pn); 60 | } 61 | 62 | if( JSON5 ) { 63 | console.log( "JSON5 v JSOX" ); 64 | console.log( "stringify", n5.sn/x.sn); 65 | console.log( "parse ", n5.pn/x.pn); 66 | } 67 | 68 | if( JSON5 && JSON6 ) { 69 | console.log( "JSON5 v JSON6" ); 70 | console.log( "stringify", n5.sn/n6.sn); 71 | console.log( "parse ", n5.pn/n6.pn); 72 | } 73 | 74 | 75 | if( JSON6 ) { 76 | console.log( "JSON6 v JSONX" ); 77 | console.log( "stringify", n6.sn/x.sn); 78 | console.log( "parse ", n6.pn/x.pn); 79 | } -------------------------------------------------------------------------------- /tests/data/rawtest.js: -------------------------------------------------------------------------------- 1 | const JSOX = require( "../.." ); 2 | 3 | var FS = require('fs'); 4 | 5 | //console.log( "Magic?", JSOX.stringify(global,null,3)); 6 | 7 | function stringTest(init) { 8 | var _private = init; 9 | Object.assign( this, { 10 | set Value(val) { 11 | _private = val; 12 | }, 13 | get Value() { 14 | return _private; 15 | } 16 | 17 | }); 18 | } 19 | stringTest.prototype.toString = function() { 20 | return '"' + this.Value + '"'; 21 | } 22 | 23 | JSOX.fromJSOX( "stringTest", function() { 24 | //console.log( "Resuurect from String:[%s]", this ); 25 | return new stringTest( this ); 26 | } ); 27 | 28 | JSOX.registerToJSOX( "stringTest", stringTest, stringTest.prototype.toString ); 29 | 30 | JSOX.fromJSOX( "arrayTest", function() { 31 | //console.log( "Resuurect from Array:[%s]", this ); 32 | return this; 33 | } ); 34 | JSOX.fromJSOX( "objectTest", function() { 35 | //console.log( "Resuurect from Object:[%s]", this ); 36 | return this; 37 | } ); 38 | 39 | function Color(init) { 40 | if( init ) { 41 | var c = Number(init ); 42 | this.r = ( c / 0x10000 ) &0xFF; 43 | this.g = ( c / 0x100 ) &0xFF; 44 | this.b = ( c / 0x1 ) &0xFF; 45 | } else { 46 | this.r=1; 47 | this.g=2; 48 | this.b=3; 49 | } 50 | this.toString = function() { return '"' + (this.r*0x10000 + this.g*0x100 + this.b) + '"' } 51 | } 52 | 53 | JSOX.addType( "color", Color 54 | , function() { return this.toString(); } 55 | , function() { return new Color(this); } 56 | ); 57 | 58 | 59 | // Modeled off of (v0.6.18 link; check latest too): 60 | // https://github.com/joyent/node/blob/v0.6.18/lib/module.js#L468-L472 61 | require.extensions['.jsox'] = function (module, filename) { 62 | var content = FS.readFileSync(filename, 'utf8'); 63 | module.exports = JSOX.parse(content); 64 | }; 65 | 66 | for( var n = 2; n < process.argv.length; n++ ) { 67 | var object = require( process.argv[n] ); 68 | console.log( "OUT:", process.argv[n], object ); 69 | var fileagain = JSOX.stringify( object ); 70 | var object2 = JSOX.parse( fileagain ); 71 | var fileagain2 = JSOX.stringify( object2 ); 72 | if( fileagain != fileagain2 ) { 73 | console.log( "Failed:", process.argv[n] ); 74 | console.log( fileagain ); 75 | console.log( fileagain2 ); 76 | process.exit( -1 ); 77 | } 78 | 79 | //console.log( "ENC:", JSOX.stringify( object, null, 3 ) ); 80 | } 81 | 82 | 83 | -------------------------------------------------------------------------------- /tests/data/stest.js: -------------------------------------------------------------------------------- 1 | const JSOX = require( "../.." ); 2 | 3 | var FS = require('fs'); 4 | 5 | // Modeled off of (v0.6.18 link; check latest too): 6 | // https://github.com/joyent/node/blob/v0.6.18/lib/module.js#L468-L472 7 | require.extensions['.jsox'] = function (module, filename) { 8 | var content = FS.readFileSync(filename, 'utf8'); 9 | module.exports = JSOX.parse(content); 10 | }; 11 | 12 | 13 | function stringTest(init) { 14 | var _private = init; 15 | Object.assign( this, { 16 | set Value(val) { 17 | _private = val; 18 | }, 19 | get Value() { 20 | return _private; 21 | } 22 | 23 | }); 24 | } 25 | stringTest.prototype.toString = function() { 26 | return '"' + this.Value + '"'; 27 | } 28 | 29 | JSOX.registerFromJSOX( "stringTest", function() { 30 | console.log( "Resuurect from String:[%s]", this ); 31 | return new stringTest( this ); 32 | } ); 33 | 34 | JSOX.registerToJSOX( "stringTest", stringTest.prototype, stringTest.prototype.toString ); 35 | 36 | JSOX.registerFromJSOX( "arrayTest", function() { 37 | console.log( "Resuurect from Array:[%s]", JSON.stringify(this )); 38 | return this; 39 | } ); 40 | JSOX.registerFromJSOX( "objectTest", function() { 41 | console.log( "Resuurect from Object:[%s]", this ); 42 | return this; 43 | } ); 44 | 45 | function Color(init) { 46 | if( init ) { 47 | var c = Number(init ); 48 | this.r = ( c / 0x10000 ) &0xFF; 49 | this.g = ( c / 0x100 ) &0xFF; 50 | this.b = ( c / 0x1 ) &0xFF; 51 | } else { 52 | this.r=1; 53 | this.g=2; 54 | this.b=3; 55 | } 56 | this.toString = function() { return '"' + (this.r*0x10000 + this.g*0x100 + this.b) + '"' } 57 | } 58 | 59 | JSOX.registerToFrom( "color", Color.prototype 60 | , function() { console.log( "calling tojsox?", this ); return this.toString(); } 61 | , function() { 62 | console.log( "Resuurect from String:[%s]", this ); 63 | return new Color(this); 64 | } 65 | ); 66 | 67 | 68 | for( var n = 2; n < process.argv.length; n++ ) { 69 | loadFile(n); 70 | function loadFile( n ) { 71 | var content = FS.readFileSync(process.argv[n], 'utf8'); 72 | 73 | function logObject( obj ) { 74 | console.log( "OUT:", obj ); 75 | console.log( "ENC:", JSOX.stringify( obj ) ); 76 | console.log( "ENC:", JSOX.stringify( obj, null, 3 ) ); 77 | } 78 | console.log( "File:", process.argv[n] ); 79 | var parser = JSOX.begin( logObject ); 80 | parser.write( content ); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /test/1.2.106-base64.mjs: -------------------------------------------------------------------------------- 1 | import {JSOX} from "jsox"; 2 | /* 3 | process.on("beforeExit", ()=>{ console.log( "EXITING" ) } ); 4 | process.on("uncaughtException",(a,b)=>{ 5 | console.log( "test", a, b ); 6 | } ); 7 | 8 | function describe(a,b) { console.log( "doing:", a ); return b() }; 9 | function it(a,b) { console.log( "test:", a ); return b() }; 10 | let threw = null; 11 | function expect(a) { if( "function" === typeof a ) { try { threw = null; a(); } catch(err){threw=err}; } 12 | return ({ to: {deep:{ equal(b) { console.log( "did",a,"=",b); } } 13 | , equal(b) { console.log( "did",a,"=",b); } 14 | , throw(a) {console.log( "Success:error?", threw ) } } }); } 15 | */ 16 | 17 | describe('Added in 1.0.106 (base64)', function () { 18 | 19 | 20 | 21 | it( 'Accepts $ and _ for encoding', function() { 22 | //console.log( "Parsed:", JSOX.parse( '{\n\t"a" : "b", "c" : "d" }' ) ) 23 | //console.log( "Parsed:", JSOX.parse( '{\n\t"a" : "b", "c" : "d" }' ) ) 24 | const buf2 = JSOX.parse( '{buf:ab["+/+/"] }' ); 25 | const buf = JSOX.parse( '{buf:ab[$_$_] }' ); 26 | const outbuf = JSOX.stringify( buf ); 27 | //console.log( 'buf:', outbuf, buf, "B", buf2 ); 28 | expect( JSOX.stringify( buf2 ) ) 29 | .to.equal( '{buf:ab[$_$_]}' ); 30 | expect( JSOX.stringify( buf ) ) 31 | .to.equal( '{buf:ab[$_$_]}' ); 32 | 33 | expect( JSOX.parse( '{buf:ab["+/+/"] }' ) ) 34 | .to.deep.equal( buf ); 35 | expect( JSOX.parse( '{buf:ab[$_$_] }' ) ) 36 | .to.deep.equal( buf2 ); 37 | // console.log( "Fail:", obj ); 38 | } ) 39 | 40 | 41 | 42 | it( 'Accepts crashes on \ for encoding', function() { 43 | //console.log( "Parsed:", JSOX.parse( '{\n\t"a" : "b", "c" : "d" }' ) ) 44 | //console.log( "Parsed:", JSOX.parse( '{\n\t"a" : "b", "c" : "d" }' ) ) 45 | expect( function() { 46 | const buf2 = JSOX.parse( '{buf:ab[+/+/] }' ); 47 | }).to.throw(Error ); 48 | const buf = JSOX.parse( '{buf:ab[$_$_] }' ); 49 | expect( JSOX.stringify(buf ) ).to.equal( '{buf:ab[$_$_]}' ); 50 | expect( JSOX.stringify(JSOX.parse('{buf:ab["+/+/"] }') ) ).to.equal( '{buf:ab[$_$_]}' ); 51 | //console.log( "Buf is currently:", JSOX.stringify(buf ) ); 52 | // fault while parsing; '+' unexpected at 11 (near '[+/[+]/] }') [1:12] 53 | } ) 54 | 55 | } ) 56 | -------------------------------------------------------------------------------- /test/testObject.js: -------------------------------------------------------------------------------- 1 | 2 | var JSON = require( ".." ) 3 | 4 | const s = ` 5 | { 6 | name: "jsox", 7 | version: "1.1.122", 8 | description: "Java Script Object eXchange.", 9 | keywords: [ 10 | "jsox","json", 11 | "macro","template","class","recursive","circular","cyclic" 12 | ], 13 | author: "d3x0r ", 14 | contributors: [ 15 | ], 16 | "@std/esm": "cjs", 17 | module: "lib/jsox.mjs", 18 | main: "lib/jsox.js", 19 | browser: "lib/jsox.es6.js.gz", 20 | bin: "lib/cli.js", 21 | files: [ 22 | "lib/" 23 | ], 24 | dependencies: {}, 25 | 26 | devDependencies: { 27 | core-js: "latest", 28 | rollup: "^1.20", 29 | eslint: "latest", 30 | nyc: "latest", 31 | mocha: "^3", 32 | chai: "^3", 33 | acorn: "^6", 34 | lint-staged: "^10.2.2", 35 | // '/' is a comment character, and needs quotes 36 | "@rollup/plugin-buble": "latest", 37 | "@rollup/plugin-commonjs": "latest", 38 | "@rollup/plugin-node-resolve": "latest", 39 | "@rollup/plugin-strip": "latest", 40 | rollup-plugin-terser: "latest" 41 | }, 42 | } 43 | ` 44 | 45 | 46 | describe( "Parse some live data", function() { 47 | it( "Works", function() { 48 | expect( JSON.parse(s) ).to.deep.equal( 49 | 50 | { 51 | name: "jsox", 52 | version: "1.1.122", 53 | description: "Java Script Object eXchange.", 54 | keywords: [ 55 | "jsox","json", 56 | "macro","template","class","recursive","circular","cyclic" 57 | ], 58 | author: "d3x0r ", 59 | contributors: [ 60 | ], 61 | "@std/esm": "cjs", 62 | module: "lib/jsox.mjs", 63 | main: "lib/jsox.js", 64 | browser: "lib/jsox.es6.js.gz", 65 | bin: "lib/cli.js", 66 | files: [ 67 | "lib/" 68 | ], 69 | dependencies: {}, 70 | 71 | devDependencies: { 72 | "core-js": "latest", 73 | rollup: "^1.20", 74 | eslint: "latest", 75 | nyc: "latest", 76 | mocha: "^3", 77 | chai: "^3", 78 | acorn: "^6", 79 | "lint-staged": "^10.2.2", 80 | // '/' is a comment character, and needs quotes 81 | "@rollup/plugin-buble": "latest", 82 | "@rollup/plugin-commonjs": "latest", 83 | "@rollup/plugin-node-resolve": "latest", 84 | "@rollup/plugin-strip": "latest", 85 | "rollup-plugin-terser": "latest" 86 | }, 87 | } 88 | ) 89 | }); 90 | 91 | }); 92 | 93 | -------------------------------------------------------------------------------- /tests/data/rawtest.mjs: -------------------------------------------------------------------------------- 1 | import {JSOX} from "../../lib/jsox.mjs"; 2 | import FS from "fs"; 3 | 4 | 5 | //console.log( "Magic?", JSOX.stringify(global,null,3)); 6 | 7 | function stringTest(init) { 8 | var _private = init; 9 | Object.assign( this, { 10 | set Value(val) { 11 | _private = val; 12 | }, 13 | get Value() { 14 | return _private; 15 | } 16 | 17 | }); 18 | } 19 | stringTest.prototype.toString = function() { 20 | return '"' + this.Value + '"'; 21 | } 22 | 23 | JSOX.fromJSOX( "stringTest", function() { 24 | //console.log( "Resuurect from String:[%s]", this ); 25 | return new stringTest( this ); 26 | } ); 27 | 28 | JSOX.registerToJSOX( "stringTest", stringTest, stringTest.prototype.toString ); 29 | 30 | JSOX.fromJSOX( "arrayTest", function() { 31 | //console.log( "Resuurect from Array:[%s]", this ); 32 | return this; 33 | } ); 34 | JSOX.fromJSOX( "objectTest", function() { 35 | //console.log( "Resuurect from Object:[%s]", this ); 36 | return this; 37 | } ); 38 | 39 | function Color(init) { 40 | if( init ) { 41 | var c = Number(init ); 42 | this.r = ( c / 0x10000 ) &0xFF; 43 | this.g = ( c / 0x100 ) &0xFF; 44 | this.b = ( c / 0x1 ) &0xFF; 45 | } else { 46 | this.r=1; 47 | this.g=2; 48 | this.b=3; 49 | } 50 | this.toString = function() { return '"' + (this.r*0x10000 + this.g*0x100 + this.b) + '"' } 51 | } 52 | 53 | JSOX.addType( "color", Color 54 | , function() { return this.toString(); } 55 | , function() { return new Color(this); } 56 | ); 57 | 58 | 59 | // Modeled off of (v0.6.18 link; check latest too): 60 | // https://github.com/joyent/node/blob/v0.6.18/lib/module.js#L468-L472 61 | /* 62 | require.extensions['.jsox'] = function (module, filename) { 63 | var content = FS.readFileSync(filename, 'utf8'); 64 | module.exports = JSOX.parse(content); 65 | }; 66 | */ 67 | 68 | function require(filename) { 69 | var content = FS.readFileSync(filename, 'utf8'); 70 | return JSOX.parse(content); 71 | 72 | } 73 | 74 | for( var n = 2; n < process.argv.length; n++ ) { 75 | var object = require( process.argv[n] ); 76 | //console.log( "OUT:", process.argv[n], object ); 77 | var fileagain = JSOX.stringify( object ); 78 | var object2 = JSOX.parse( fileagain ); 79 | var fileagain2 = JSOX.stringify( object2 ); 80 | if( fileagain != fileagain2 ) { 81 | console.log( "Failed:", process.argv[n] ); 82 | console.log( fileagain ); 83 | console.log( fileagain2 ); 84 | process.exit( -1 ); 85 | } 86 | 87 | //console.log( "ENC:", JSOX.stringify( object, null, 3 ) ); 88 | } 89 | 90 | 91 | -------------------------------------------------------------------------------- /test/benchmarks/fundamentals/testNumberConvert.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | let negative = true; 4 | const val = { string : "1234", negative : false }; 5 | 6 | describe('Number conversions', function () { 7 | this.timeout(10000); 8 | it('Negative number', function () { 9 | const start = Date.now(); 10 | for( let m = 0; m < 5000; m++ ) { 11 | val.negative = m & 1; 12 | for( let n = 0; n < 100000; n++ ) 13 | //negative?-Number( "1234" ):Number("1234"); 14 | val.negative ? -Number(val.string) : Number(val.string); 15 | } 16 | console.log( "took:", Date.now() - start ); 17 | }); 18 | it('Negative number (single negating expression)', function () { 19 | const start = Date.now(); 20 | 21 | for( let m = 0; m < 5000; m++ ) { 22 | val.negative = m & 1; 23 | for( let n = 0; n < 100000; n++ ) 24 | (val.negative ? -1 : 1) * Number(val.string); 25 | // Number("1234") * (negative?-1:1); 26 | } 27 | console.log( "took:", Date.now() - start ); 28 | 29 | }); 30 | it('Negative number (multiplying negative factor)', function () { 31 | const start = Date.now(); 32 | 33 | for( let m = 0; m < 5000; m++ ) { 34 | val.negative = m & 1; 35 | for( let n = 0; n < 100000; n++ ) 36 | Number(val.string) * (val.negative ? -1 : 1); 37 | // Number("1234") * (negative?-1:1); 38 | } 39 | console.log( "took:", Date.now() - start ); 40 | 41 | }); 42 | it('Negative number (changing variable)', function () { 43 | const start = Date.now(); 44 | for( let m = 0; m < 5000; m++ ) { 45 | negative = m & 1; 46 | for( let n = 0; n < 100000; n++ ) 47 | // negative ? -Number( "1234" ) : Number("1234"); 48 | negative ? -Number(val.string) : Number(val.string); 49 | } 50 | console.log( "took:", Date.now() - start ); 51 | 52 | }); 53 | it('Negative number (changing variable and multiplying)', function () { 54 | const start = Date.now(); 55 | 56 | for( let m = 0; m < 5000; m++ ) { 57 | negative = m & 1; 58 | for( let n = 0; n < 100000; n++ ) 59 | Number(val.string) * (negative ? -1 : 1); 60 | // Number("1234") * (negative ? -1 : 1); 61 | } 62 | console.log( "took:", Date.now() - start ); 63 | 64 | }); 65 | it('Negative number (changing variable and multiplying in front)', function () { 66 | const start = Date.now(); 67 | 68 | for( let m = 0; m < 5000; m++ ) { 69 | negative = m & 1; 70 | for( let n = 0; n < 100000; n++ ) 71 | (negative ? -1 : 1) * Number(val.string); 72 | // Number("1234") * (negative ? -1 : 1); 73 | } 74 | console.log( "took:", Date.now() - start ); 75 | 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /test/streamTest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSON6 = require( '..' ); 3 | const fs = require( 'fs' ); 4 | const path = require( 'path' ); 5 | 6 | const buf = fs.readFileSync( path.join(__dirname, 'stream.json6') ); 7 | const msg = buf.toString( 'utf8' ); 8 | 9 | describe('Streaming', function () { 10 | it('Streams various objects', function () { 11 | const results = []; 12 | const parser = JSON6.begin(function (val) { 13 | //console.log( "Got Object:", val ); 14 | results.push(val); 15 | }); 16 | 17 | for( 18 | let result = parser.write( msg ); 19 | result > 0; 20 | parser.write() 21 | ); 22 | 23 | expect(results).to.deep.equal([ 24 | 123, 25 | 456, 26 | 789, 27 | 1234, 28 | ['a','b','c'], 29 | 'This\nis\na\ntest', 30 | { a: { b : { c : { d : 123 }, e: [154,452] }, f : 942 }, g: 'Final' } 31 | ]); 32 | }); 33 | it('Converts non-string to string and attempts to process', function () { 34 | const results = []; 35 | const parser = JSON6.begin(function (val) { 36 | //console.log( "Got Object:", val ); 37 | results.push(val); 38 | }); 39 | 40 | expect(function () { 41 | parser.write({}); 42 | //}).to.throw(Error, /fault parsing 'o' unexpected/); 43 | }).to.throw(Error, /Double string error, no constructor for: new object\(Object\)/); 44 | }); 45 | it('handles incomplete string key in chunks', function () { 46 | const results = []; 47 | const parser = JSON6.begin(function (val) { 48 | //console.log( "Got Object:", val ); 49 | results.push(val); 50 | }); 51 | 52 | for( 53 | let result = parser.write( '{"' ); 54 | result > 0; 55 | parser.write() 56 | ); 57 | parser.write( 'a' ); 58 | parser.write( '"' ); 59 | 60 | expect(results).to.deep.equal([]); 61 | }); 62 | it('Supports reviver', function () { 63 | const results = []; 64 | const parser = JSON6.begin(function (val) { 65 | //console.log( "Got Object:", val ); 66 | }, function (a, b) { 67 | results.push([a, b]); 68 | if (a === 'd') { 69 | return undefined; 70 | } 71 | return b; 72 | } ); 73 | 74 | // Add temporarily to prototype to check coverage of 75 | // `hasOwnProperty` filter 76 | Object.prototype.ttt = function () {}; 77 | parser.write('{a: {b: {c: 5}, d: 8}}'); 78 | delete Object.prototype.ttt; 79 | 80 | expect(results).to.deep.equal([ 81 | ['c', 5], 82 | ['b', { 83 | c: 5 84 | }], 85 | ['d', 8], 86 | ['a', { 87 | b: { 88 | c: 5 89 | } 90 | }], 91 | ['', { 92 | a: { 93 | b: { 94 | c: 5 95 | } 96 | } 97 | }] 98 | ]); 99 | }); 100 | }); 101 | -------------------------------------------------------------------------------- /tests/json6TestObject2.js: -------------------------------------------------------------------------------- 1 | 2 | var JSON6 = require( ".." ); 3 | var s = `{ 4 | "name": "@std/esm", 5 | "version": "0.18.0", 6 | "description": "Enable ES modules in Node today!", 7 | "keywords": "commonjs, ecmascript, export, import, modules, node, require", 8 | "repository": "standard-things/esm", 9 | "license": "MIT", 10 | "author": "John-David Dalton ", 11 | "main": "index.js", 12 | "private": true, 13 | "@std/esm": true, 14 | "engines": { 15 | "node": ">=4" 16 | }, 17 | "scripts": { 18 | "prebuild:prod": "optional-dev-dependency", 19 | "precommit": "npm run lint", 20 | "prelint": "npm run pretest", 21 | "prepub": "npm run test:prod", 22 | "pretest": "npm run build -- --test", 23 | "pretest:prod": "npm run build:prod -- --test", 24 | "build": "node script/build.js", 25 | "build:prod": "npm run build -- --prod", 26 | "clean": "node script/clean.js", 27 | "lint": "eslint \\'**/*.{js,mjs}\\' --fix --quiet", 28 | "pub": "node script/publish.js", 29 | "test": "node script/test.js", 30 | "test:prod": "node script/test.js --prod" 31 | }, 32 | "devDependencies": { 33 | "@babel/core": "^7.0.0-beta.34", 34 | "@babel/plugin-proposal-class-properties": "^7.0.0-beta.34", 35 | "@babel/plugin-transform-block-scoping": "^7.0.0-beta.34", 36 | "@babel/preset-env": "^7.0.0-beta.34", 37 | "@babel/register": "^7.0.0-beta.34", 38 | "acorn": "^5.2.1", 39 | "ava": "^0.24.0", 40 | "babel-eslint": "^8.0.3", 41 | "babel-loader": "^8.0.0-beta.0", 42 | "babel-plugin-transform-for-of-as-array": "^1.0.4", 43 | "download": "^6.2.5", 44 | "eslint": "^4.12.0", 45 | "eslint-plugin-import": "^2.7.0", 46 | "eslint-plugin-node": "^5.2.0", 47 | "execa": "^0.8.0", 48 | "fs-extra": "^4.0.3", 49 | "globby": "^7.1.1", 50 | "husky": "^0.14.3", 51 | "jest": "^21.2.1", 52 | "json-6": "^0.1.120", 53 | "minizlib": "^1.0.4", 54 | "mocha": "^4.0.1", 55 | "mock-stdio": "^1.0.0", 56 | "nop": "^1.0.0", 57 | "nyc": "^11.3.0", 58 | "optimize-js-plugin": "0.0.4", 59 | "optional-dev-dependency": "^2.0.1", 60 | "pify": "^3.0.0", 61 | "pm2": "^2.8.0", 62 | "semver": "^5.4.1", 63 | "trash": "^4.2.1", 64 | "typescript": "^2.6.1", 65 | "uglify-es": "^3.2.1", 66 | "uglifyjs-webpack-plugin": "^1.1.1", 67 | "webpack": "^3.10.0", 68 | "webpack-bundle-analyzer": "^2.8.3", 69 | "webpack-common-shake": "^1.5.3", 70 | "yargs": "^10.0.3" 71 | }, 72 | "optionalDevDependencies": { 73 | "node-zopfli": "^2.0.2" 74 | }, 75 | "files": [ 76 | "index.js", 77 | "esm.js.gz" 78 | ] 79 | }` 80 | 81 | console.log( JSON6.parse( s ) ); 82 | -------------------------------------------------------------------------------- /tests/TestObjectKeys.js: -------------------------------------------------------------------------------- 1 | 2 | var JSON6 = require( ".." ); 3 | 4 | 5 | 6 | try { 7 | var result = JSON6.parse( "{ my- key:3}" ); 8 | console.log( "result:", result ); 9 | } catch( err ) { 10 | console.log( 'error expected:', err.message ); 11 | } 12 | 13 | try { 14 | var result = JSON6.parse( "{ my - key:3}" ); 15 | console.log( "result:", result ); 16 | } catch( err ) { 17 | console.log( 'error expected:', err.message ); 18 | } 19 | 20 | try { 21 | var result = JSON6.parse( "{ my-key { failure:true}:3}" ); 22 | console.log( "result:", result ); 23 | } catch( err ) { 24 | console.log( 'error expected:', err.message ); 25 | } 26 | 27 | try { 28 | var result = JSON6.parse( "{ { my-key:3 } }" ); 29 | console.log( "result:", result ); 30 | } catch( err ) { 31 | console.log( 'error expected:', err.message ); 32 | } 33 | 34 | try { 35 | var result = JSON6.parse( "{ [ my-key:3 } }" ); 36 | console.log( "result:", result ); 37 | } catch( err ) { 38 | console.log( 'error expected:', err.message ); 39 | } 40 | 41 | try { 42 | var result = JSON6.parse( "{ my-key[:3 } }" ); 43 | console.log( "result:", result ); 44 | } catch( err ) { 45 | console.log( 'error expected:', err.message ); 46 | } 47 | 48 | try { 49 | var result = JSON6.parse( "{ my-key]:3 } }" ); 50 | console.log( "result:", result ); 51 | } catch( err ) { 52 | console.log( 'error expected:', err.message ); 53 | } 54 | 55 | try { 56 | var result = JSON6.parse( "{ my-key [:3 } }" ); 57 | console.log( "result:", result ); 58 | } catch( err ) { 59 | console.log( 'error expected:', err.message ); 60 | } 61 | 62 | try { 63 | var result = JSON6.parse( "{ my-key ]:3 } }" ); 64 | console.log( "result:", result ); 65 | } catch( err ) { 66 | console.log( 'error expected:', err.message ); 67 | } 68 | 69 | 70 | 71 | var result = JSON6.parse( "{ 'my - key':3}" ); 72 | console.log( "result:", result ); 73 | 74 | var result = JSON6.parse( "{ my-key\\m&m+*|:3}" ); 75 | console.log( "result:", result ); 76 | 77 | var result = JSON6.parse( "{ my-key //test \n :3}" ); 78 | console.log( "result:", result ); 79 | 80 | var result = JSON6.parse( "{ my-key /*test */ :3}" ); 81 | console.log( "result:", result ); 82 | 83 | 84 | 85 | 86 | /* 87 | 88 | { my- key:3} // fault 89 | { my - key:3} // fault 90 | { my-key { failure:true}:3} // fault 91 | { { my-key:3 } } // fault 92 | { [ my-key:3 } } // fault 93 | { my-key [:3 } } // fault 94 | { my-key ]:3 } } // fault 95 | { my-key[:3 } } // fault 96 | { my-key]:3 } } // fault 97 | 98 | { 'my - key':3} // valid 99 | { my-key\\m&m+*|:3} // valid 100 | 101 | { my-key //test 102 | :3} // valid 103 | 104 | { my-key /*test * / :3} // valid 105 | 106 | */ -------------------------------------------------------------------------------- /test/json6TestObject2.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSON6 = require( ".." ); 3 | 4 | const obj = { 5 | "name": "@std/esm", 6 | "version": "0.18.0", 7 | "description": "Enable ES modules in Node today!", 8 | "keywords": "commonjs, ecmascript, export, import, modules, node, require", 9 | "repository": "standard-things/esm", 10 | "license": "MIT", 11 | "author": "John-David Dalton ", 12 | "main": "index.js", 13 | "private": true, 14 | "@std/esm": true, 15 | "engines": { 16 | "node": ">=4" 17 | }, 18 | "scripts": { 19 | "prebuild:prod": "optional-dev-dependency", 20 | "precommit": "npm run lint", 21 | "prelint": "npm run pretest", 22 | "prepub": "npm run test:prod", 23 | "pretest": "npm run build -- --test", 24 | "pretest:prod": "npm run build:prod -- --test", 25 | "build": "node script/build.js", 26 | "build:prod": "npm run build -- --prod", 27 | "clean": "node script/clean.js", 28 | "lint": "eslint \\'**/*.{js,mjs}\\' --fix --quiet", 29 | "pub": "node script/publish.js", 30 | "test": "node script/test.js", 31 | "test:prod": "node script/test.js --prod" 32 | }, 33 | "devDependencies": { 34 | "@babel/core": "^7.0.0-beta.34", 35 | "@babel/plugin-proposal-class-properties": "^7.0.0-beta.34", 36 | "@babel/plugin-transform-block-scoping": "^7.0.0-beta.34", 37 | "@babel/preset-env": "^7.0.0-beta.34", 38 | "@babel/register": "^7.0.0-beta.34", 39 | "acorn": "^5.2.1", 40 | "ava": "^0.24.0", 41 | "babel-eslint": "^8.0.3", 42 | "babel-loader": "^8.0.0-beta.0", 43 | "babel-plugin-transform-for-of-as-array": "^1.0.4", 44 | "download": "^6.2.5", 45 | "eslint": "^4.12.0", 46 | "eslint-plugin-import": "^2.7.0", 47 | "eslint-plugin-node": "^5.2.0", 48 | "execa": "^0.8.0", 49 | "fs-extra": "^4.0.3", 50 | "globby": "^7.1.1", 51 | "husky": "^0.14.3", 52 | "jest": "^21.2.1", 53 | "json-6": "^0.1.120", 54 | "minizlib": "^1.0.4", 55 | "mocha": "^4.0.1", 56 | "mock-stdio": "^1.0.0", 57 | "nop": "^1.0.0", 58 | "nyc": "^11.3.0", 59 | "optimize-js-plugin": "0.0.4", 60 | "optional-dev-dependency": "^2.0.1", 61 | "pify": "^3.0.0", 62 | "pm2": "^2.8.0", 63 | "semver": "^5.4.1", 64 | "trash": "^4.2.1", 65 | "typescript": "^2.6.1", 66 | "uglify-es": "^3.2.1", 67 | "uglifyjs-webpack-plugin": "^1.1.1", 68 | "webpack": "^3.10.0", 69 | "webpack-bundle-analyzer": "^2.8.3", 70 | "webpack-common-shake": "^1.5.3", 71 | "yargs": "^10.0.3" 72 | }, 73 | "optionalDevDependencies": { 74 | "node-zopfli": "^2.0.2" 75 | }, 76 | "files": [ 77 | "index.js", 78 | "esm.js.gz" 79 | ] 80 | }; 81 | 82 | describe('JSON6 test object 2', function () { 83 | it('Parses (`package.json`) object', function () { 84 | const result = JSON6.parse( JSON.stringify(obj) ); 85 | //console.log(result); 86 | expect(result).to.deep.equal(obj); 87 | }); 88 | }); 89 | -------------------------------------------------------------------------------- /tests/data/nested.jsox: -------------------------------------------------------------------------------- 1 | { 2 | accruals: { 3 | activities: [{ 4 | accrual_activity_id: "WquNzWNPX1g7TcU1", 5 | groups: [], 6 | inputs: [], 7 | name: "Activity 1" 8 | }, { 9 | accrual_activity_id: "oyZpcHztR_B5C8Re", 10 | groups: [{ 11 | accrual_group_id: "4HR7gVd7Np_4eSWf", 12 | activities: [ref["accruals", "activities", 1, "groups", 0]], 13 | everyTally: 0, 14 | housePercent: 12, 15 | inputs: [], 16 | last_accrual_id: null, 17 | last_accrual_set_id: null, 18 | name: "Jackpot 2", 19 | pricePerPack: null, 20 | startingValue: 150000, 21 | thresholds: [] 22 | }], 23 | inputs: [], 24 | name: "Activity 12" 25 | }, { 26 | accrual_activity_id: "e64LHFlm3O4YW4Ut", 27 | groups: [], 28 | inputs: [], 29 | name: "Activity 23" 30 | }, { 31 | accrual_activity_id: "ui3TyYxtv4_kYjWU", 32 | groups: [], 33 | inputs: [], 34 | name: "Activity 3" 35 | }, { 36 | accrual_activity_id: "YpO43iXyjdjlAsCn", 37 | groups: [], 38 | inputs: [], 39 | name: "Activity 4" 40 | }], 41 | groups: [ref["accruals", "activities", 1, "groups", 0], { 42 | accrual_group_id: "uzMN2iCOcmp_Az0b", 43 | activities: [], 44 | everyTally: 0, 45 | housePercent: 20, 46 | inputs: [], 47 | last_accrual_id: null, 48 | last_accrual_set_id: null, 49 | name: "Jackpot 1", 50 | pricePerPack: null, 51 | startingValue: 173400, 52 | thresholds: [] 53 | }, { 54 | accrual_group_id: "YwOp2uHlYS0E6WnV", 55 | activities: [], 56 | everyTally: 1, 57 | housePercent: 15, 58 | inputs: [], 59 | last_accrual_id: null, 60 | last_accrual_set_id: null, 61 | name: "Jackpot 3", 62 | pricePerPack: null, 63 | startingValue: 432100, 64 | thresholds: [] 65 | }], 66 | inputs: [{ 67 | accrual_input_group_id: "LfCoMyNj0iIXyK7R", 68 | defaultAmount: 0, 69 | fixedAmount: 12300, 70 | groups: [], 71 | isDaily: 0, 72 | isIncrements: 0, 73 | isWeekly: 0, 74 | minimum: 3033, 75 | name: "Sales 1", 76 | scalePrice: 0, 77 | sqlStatement: "select 123", 78 | useDefault: 0, 79 | useMimimum: 0, 80 | useMinimum: 1, 81 | useScalePrice: 0 82 | }] 83 | }, 84 | op: "accruals" 85 | } -------------------------------------------------------------------------------- /tests/json6NumberTest.js: -------------------------------------------------------------------------------- 1 | 2 | var JSON = require( ".." ); 3 | var start; 4 | 5 | 6 | 7 | console.log( JSON.parse( "-1234" ) ); 8 | start = Date.now(); 9 | for( var m = 0; m < 40; m++ ) 10 | for( n = 0; n < 100000; n++ ) 11 | JSON.parse( "-1234" ); 12 | console.log( "took:", Date.now() - start ); 13 | 14 | console.log( JSON.parse( "1234" ) ); 15 | start = Date.now(); 16 | for( var m = 0; m < 40; m++ ) 17 | for( n = 0; n < 100000; n++ ) 18 | JSON.parse( "1234" ); 19 | console.log( "took:", Date.now() - start ); 20 | 21 | 22 | console.log( JSON.parse( "{a:1234}" ) ); 23 | start = Date.now(); 24 | for( n = 0; n < 2000000; n++ ) 25 | JSON.parse( "{a:1234}" ); 26 | console.log( "took:", Date.now() - start ); 27 | 28 | 29 | 30 | 31 | console.log( JSON.parse( "{a:-1234}" ) ); 32 | start = Date.now(); 33 | for( n = 0; n < 2000000; n++ ) 34 | JSON.parse( "{a:-1234}" ); 35 | console.log( "took:", Date.now() - start ); 36 | 37 | 38 | console.log( JSON.parse( "[1234]" ) ); 39 | start = Date.now(); 40 | for( n = 0; n < 2000000; n++ ) 41 | JSON.parse( "[1234]" ); 42 | console.log( "took:", Date.now() - start ); 43 | 44 | console.log( JSON.parse( "[-1234]" ) ); 45 | start = Date.now(); 46 | for( n = 0; n < 2000000; n++ ) 47 | JSON.parse( "[-1234]" ); 48 | console.log( "took:", Date.now() - start ); 49 | 50 | 51 | 52 | 53 | console.log( JSON.parse( "-1234" ) ); 54 | start = Date.now(); 55 | for( n = 0; n < 2000000; n++ ) 56 | JSON.parse( "-1234" ); 57 | console.log( "took:", Date.now() - start ); 58 | 59 | console.log( JSON.parse( "1234" ) ); 60 | start = Date.now(); 61 | for( n = 0; n < 2000000; n++ ) 62 | JSON.parse( "1234" ); 63 | console.log( "took:", Date.now() - start ); 64 | 65 | 66 | 67 | console.log( JSON.parse( "{a:0.1234}" ) ); 68 | start = Date.now(); 69 | for( n = 0; n < 1000000; n++ ) 70 | JSON.parse( "{a:0.1234}" ); 71 | console.log( "took:", Date.now() - start ); 72 | 73 | console.log( JSON.parse( "{a:-01234}" ) ); 74 | start = Date.now(); 75 | for( n = 0; n < 1009000; n++ ) 76 | JSON.parse( "{a:-01234}" ); 77 | console.log( "took:", Date.now() - start ); 78 | 79 | 80 | console.log( JSON.parse( "{a:01234}" ) ); 81 | start = Date.now(); 82 | for( n = 0; n < 1009000; n++ ) 83 | JSON.parse( "{a:01234}" ); 84 | console.log( "took:", Date.now() - start ); 85 | 86 | 87 | console.log( JSON.parse( "[01234e3]" ) ); 88 | start = Date.now(); 89 | for( n = 0; n < 1000000; n++ ) 90 | JSON.parse( "[01234e3]" ); 91 | console.log( "took:", Date.now() - start ); 92 | 93 | console.log( JSON.parse( "[-0x1234]" ) ); 94 | start = Date.now(); 95 | for( var m = 0; m < 20; m++ ) 96 | for( n = 0; n < 100000; n++ ) 97 | JSON.parse( "[-0x1234]" ); 98 | console.log( "took:", Date.now() - start ); 99 | 100 | 101 | //console.log( "Waiting forever..." ); 102 | //function wait() { setTimeout( wait, 2000 ) } 103 | //wait(); 104 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | const nodeResolve = require('@rollup/plugin-node-resolve') 2 | const resolve = ("function" === typeof nodeResolve )?nodeResolve:nodeResolve.nodeResolve; 3 | const commonjs = require('@rollup/plugin-commonjs') 4 | //const closure = require('rollup-plugin-closure-compiler' ); 5 | const terser = require('@rollup/plugin-terser') 6 | //const gzip = require( 'rollup-plugin-gzip').default 7 | const pkg = require('./package.json') 8 | 9 | // Last time through gzip plugin refused to write compressed output. 10 | 11 | module.exports = [ 12 | // ES6 Modules Non-minified 13 | { 14 | input: 'lib/index.js', 15 | output: { 16 | file: pkg.browser.replace(/\.js$/, '.mjs'), 17 | format: 'esm', 18 | }, 19 | plugins: [ 20 | resolve(),//.nodeResolve(), 21 | commonjs(), 22 | ], 23 | }, 24 | // ES6 Modules Minified 25 | { 26 | input: 'lib/index.js', 27 | output: { 28 | file: pkg.browser.replace(/\.js$/, '.min.mjs'), 29 | format: 'esm', 30 | }, 31 | plugins: [ 32 | resolve(),//.nodeResolve(), 33 | commonjs(), 34 | terser( ), 35 | ], 36 | }, 37 | // ES6 Modules Minified 38 | { 39 | input: pkg.module, 40 | output: { 41 | file: pkg.module.replace(/\.mjs$/, '.min.mjs'), 42 | exports : 'named', 43 | format: 'esm', 44 | }, 45 | plugins: [ 46 | commonjs(), 47 | terser(), 48 | ], 49 | }, 50 | // ES6 NonModule Minified 51 | { 52 | input: pkg.main, 53 | output: { 54 | file: pkg.main.replace(/\.js$/, '.min.js'), 55 | //exports : 'default', 56 | format: 'cjs', 57 | }, 58 | plugins: [ 59 | commonjs(), 60 | terser( {toplevel:false,mangle:{reserved :["exports","JSOX","version","stringifier","DateNS","toJSOX","fromJSOX","addType","escape","begin","parse","defineClass","reset"] 61 | , properties:{undeclared :false, reserved :["begin","JSOX","exports","version","stringifier","DateNS","toJSOX","fromJSOX","addType","escape","begin","parse","defineClass","reset"]}} } ), 62 | ], 63 | }, 64 | /* 65 | // ES6 Modules Minified 66 | { 67 | input: pkg.module.replace(/\.mjs$/, '.min.mjs'), 68 | output: { 69 | file: pkg.module.replace(/\.mjs$/, '.min.mjs.gz'), 70 | exports : 'named', 71 | format: 'esm', 72 | }, 73 | plugins: [ 74 | gzip(), 75 | ], 76 | }, 77 | // ES6 NonModule Minified 78 | { 79 | input: pkg.main.replace(/\.js$/, '.min.js'), 80 | output: { 81 | file: pkg.main.replace(/\.js$/, '.min.js.gz'), 82 | exports : 'named', 83 | format: 'cjs', 84 | }, 85 | plugins: [ 86 | gzip(), 87 | ], 88 | }, 89 | */ 90 | ] -------------------------------------------------------------------------------- /test/1.2.114.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | const JSOX = require( ".." ); 4 | 5 | /* 6 | process.on("beforeExit", ()=>{ console.log( "EXITING" ) } ); 7 | process.on("uncaughtException",(a,b)=>{ 8 | console.log( "test", a, b ); 9 | } ); 10 | 11 | function describe(a,b) { return b() }; 12 | function it(a,b) { return b() }; 13 | let threw = null; 14 | function expect(a) { if( "function" === typeof a ) { try { threw = null; a(); } catch(err){threw=err}; } 15 | return ({ to: {deep:{ equal(b) { console.log( "did",a,"=",b); } } 16 | , equal(b) { console.log( "did",a,"=",b); } 17 | , throw(a) {console.log( "Success:error?", threw ) } } }); } 18 | */ 19 | 20 | describe('Added in 1.2.114 (cjs)', function () { 21 | 22 | 23 | 24 | it( 'handles ref revivals(extra debug)', function() { 25 | const w1 = {A:1,end:null,start:null}; 26 | const w2 = {A:2,end:null,start:null}; 27 | const w3 = {A:3,end:null,start:null}; 28 | const w4 = {A:4,end:null,start:null}; 29 | w1.start = w2; 30 | w1.end = w3; 31 | w2.start = w1; 32 | w2.end = w4; 33 | w3.start = w1; 34 | w3.end = w4; 35 | w4.start = w2; 36 | w4.end = w3; 37 | /* 38 | {op:"move" 39 | ,walls:[ 40 | {A:1,end: 41 | {A:3,end: 42 | {A:4,end:ref["walls",0,"end"] 43 | ,start: 44 | {A:2,end:ref["walls",0,"end","end"],start:ref["walls",0]} 45 | } 46 | ,start:ref["walls",0] 47 | } 48 | ,start:ref["walls",0,"end","end","start"] 49 | } 50 | ,ref["walls",0,"end","end","start"] 51 | ,ref["walls",0,"end"] 52 | ,ref["walls",0,"end","end"]]} 53 | */ 54 | /* 55 | console.log( "walls:", w1 ); 56 | console.log( "walls:", w2 ); 57 | console.log( "walls:", w3 ); 58 | console.log( "walls:", w4 ); 59 | */ 60 | const o = {op:"move", walls: [w1,w2,w3,w4] } 61 | const str = JSOX.stringify( o ); 62 | 63 | const obj = JSOX.parse( str ); 64 | if( obj.walls[0].start === obj.walls[1] && 65 | obj.walls[0].end === obj.walls[2] && 66 | obj.walls[3].start === obj.walls[1] && 67 | obj.walls[3].end === obj.walls[2] && 68 | obj.walls[1].start === obj.walls[0] && 69 | obj.walls[1].end === obj.walls[3] && 70 | obj.walls[2].start === obj.walls[0] && 71 | obj.walls[1].end === obj.walls[3] ) { 72 | /* success */; 73 | } else { 74 | console.log( "Failed TEST:", obj, o, str ); 75 | //console.log( "\n", obj.walls[0], "\n", obj.walls[1], "\n", obj.walls[2], "\n", obj.walls[3] ); 76 | /* 77 | console.log( "\n", obj.walls[0] ); 78 | console.log( "\n", obj.walls[1] ); 79 | console.log( "\n", obj.walls[2] ); 80 | console.log( "\n", obj.walls[3] ); 81 | 82 | console.log( "walls:", w1 ); 83 | console.log( "walls:", w2 ); 84 | console.log( "walls:", w3 ); 85 | console.log( "walls:", w4 ); 86 | */ 87 | throw new Error( "Object Mis-Match") ; 88 | } 89 | const str2 = JSOX.stringify( obj ); 90 | //console.log( "got:", str ); 91 | expect( str2 ).to.equal( str2 ); 92 | 93 | } ); 94 | 95 | } ); 96 | -------------------------------------------------------------------------------- /test/1.2.114.mjs: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | import {JSOX} from "jsox"; 4 | 5 | /* 6 | process.on("beforeExit", ()=>{ console.log( "EXITING" ) } ); 7 | process.on("uncaughtException",(a,b)=>{ 8 | console.log( "test", a, b ); 9 | } ); 10 | 11 | function describe(a,b) { return b() }; 12 | function it(a,b) { return b() }; 13 | let threw = null; 14 | function expect(a) { if( "function" === typeof a ) { try { threw = null; a(); } catch(err){threw=err}; } 15 | return ({ to: {deep:{ equal(b) { console.log( "did",a,"=",b); } } 16 | , equal(b) { console.log( "did",a,"=",b); } 17 | , throw(a) {console.log( "Success:error?", threw ) } } }); } 18 | */ 19 | 20 | describe('Added in 1.2.114 (mjs)', function () { 21 | 22 | 23 | 24 | it( 'handles ref revivals(extended info)', function() { 25 | const w1 = {A:1,end:null,start:null}; 26 | const w2 = {A:2,end:null,start:null}; 27 | const w3 = {A:3,end:null,start:null}; 28 | const w4 = {A:4,end:null,start:null}; 29 | w1.start = w2; 30 | w1.end = w3; 31 | w2.start = w1; 32 | w2.end = w4; 33 | w3.start = w1; 34 | w3.end = w4; 35 | w4.start = w2; 36 | w4.end = w3; 37 | /* 38 | {op:"move" 39 | ,walls:[ 40 | {A:1,end: 41 | {A:3,end: 42 | {A:4,end:ref["walls",0,"end"] 43 | ,start: 44 | {A:2,end:ref["walls",0,"end","end"],start:ref["walls",0]} 45 | } 46 | ,start:ref["walls",0] 47 | } 48 | ,start:ref["walls",0,"end","end","start"] 49 | } 50 | ,ref["walls",0,"end","end","start"] 51 | ,ref["walls",0,"end"] 52 | ,ref["walls",0,"end","end"]]} 53 | */ 54 | /* 55 | console.log( "walls:", w1 ); 56 | console.log( "walls:", w2 ); 57 | console.log( "walls:", w3 ); 58 | console.log( "walls:", w4 ); 59 | */ 60 | const o = {op:"move", walls: [w1,w2,w3,w4] } 61 | const str = JSOX.stringify( o ); 62 | 63 | const obj = JSOX.parse( str ); 64 | if( obj.walls[0].start === obj.walls[1] && 65 | obj.walls[0].end === obj.walls[2] && 66 | obj.walls[3].start === obj.walls[1] && 67 | obj.walls[3].end === obj.walls[2] && 68 | obj.walls[1].start === obj.walls[0] && 69 | obj.walls[1].end === obj.walls[3] && 70 | obj.walls[2].start === obj.walls[0] && 71 | obj.walls[1].end === obj.walls[3] ) { 72 | /* success */; 73 | } else { 74 | console.log( "Failed TEST:", obj, o, str ); 75 | //console.log( "\n", obj.walls[0], "\n", obj.walls[1], "\n", obj.walls[2], "\n", obj.walls[3] ); 76 | /* 77 | console.log( "\n", obj.walls[0] ); 78 | console.log( "\n", obj.walls[1] ); 79 | console.log( "\n", obj.walls[2] ); 80 | console.log( "\n", obj.walls[3] ); 81 | 82 | console.log( "walls:", w1 ); 83 | console.log( "walls:", w2 ); 84 | console.log( "walls:", w3 ); 85 | console.log( "walls:", w4 ); 86 | */ 87 | throw new Error( "Object Mis-Match") ; 88 | } 89 | const str2 = JSOX.stringify( obj ); 90 | //console.log( "got:", str ); 91 | expect( str2 ).to.equal( str2 ); 92 | 93 | } ); 94 | 95 | } ); 96 | -------------------------------------------------------------------------------- /test/stringEscapes.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSON6 = require( '..' ); 3 | 4 | describe('String escapes', function () { 5 | describe('Octal escapes', function () { 6 | it('Does not parses string octal escape', function () { 7 | const result = JSON6.parse( '"\\056"' ); 8 | expect(result).to.equal('\0'+'56'); 9 | }); 10 | it('Does not parse string octal escape followed by character', function () { 11 | const result = JSON6.parse( '"\\01A"' ); 12 | expect(result).to.equal('\0' + '1A'); 13 | }); 14 | }); 15 | describe('Unicode escape', function () { 16 | it('Throws with bad Unicode escape', function () { 17 | expect(function () { 18 | JSON6.parse( '"\\u00G"' ); 19 | }).to.throw(Error, /escaped character, parsing hex|fault while parsing/); 20 | }); 21 | }); 22 | describe('Unicode wide escapes', function () { 23 | it('Parses Unicode wide escape (lower-case)', function () { 24 | const result = JSON6.parse( '"\\u{002e}"' ); 25 | expect(result).to.equal('.'); 26 | }); 27 | it('Parses Unicode wide escape (upper-case)', function () { 28 | const result = JSON6.parse( '"\\u{002E}"' ); 29 | expect(result).to.equal('.'); 30 | }); 31 | it('Throws with bad Unicode wide escape (upper-case)', function () { 32 | expect(function () { 33 | JSON6.parse( '"\\u{00G}"' ); 34 | }).to.throw(Error, /escaped character, parsing hex/); 35 | }); 36 | 37 | it('Throws with incomplete Unicode wide escape (upper-case)', function () { 38 | expect(function () { 39 | JSON6.parse( '"\\u{00F"' ); 40 | }).to.throw(Error, /Incomplete long unicode sequence|Pending value could not complete/); 41 | }); 42 | }); 43 | describe('String hex escapes', function () { 44 | it('Parses string hex', function () { 45 | const result = JSON6.parse( '"\\x2e"' ); 46 | expect(result).to.equal('.'); 47 | }); 48 | it('Throws with bad hex escape', function () { 49 | expect(function () { 50 | JSON6.parse( '"\\x0G"' ); 51 | }).to.throw(Error, /escaped character, parsing hex/); 52 | }); 53 | }); 54 | describe('Single escapes', function () { 55 | it('\\b', function () { 56 | const result = JSON6.parse( '"\\b"' ); 57 | expect(result).to.equal('\b'); 58 | }); 59 | it('\\f', function () { 60 | const result = JSON6.parse( '"\\f"' ); 61 | expect(result).to.equal('\f'); 62 | }); 63 | it('\\v', function () { 64 | const result = JSON6.parse( '"\\v"' ); 65 | expect(result).to.equal('\v'); 66 | }); 67 | it('Should throw with string closing without successor to backslash', function () { 68 | expect(function () { 69 | JSON6.parse( '"\\"' ); 70 | }).to.throw(Error); 71 | }); 72 | 73 | it('should consume carriage return escape at end of string', function () { 74 | expect(JSON6.parse( '"\\\r"' )).to.equal(''); 75 | }); 76 | 77 | it('should recover character after carriage return escape at end of string', function () { 78 | expect(JSON6.parse( '"\\\rA"' )).to.equal('A'); 79 | }); 80 | }); 81 | }); 82 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsox", 3 | "version": "1.2.124", 4 | "description": "Java Script Object eXchange.", 5 | "keywords": [ 6 | "jsox", 7 | "json", 8 | "macro", 9 | "template", 10 | "class", 11 | "recursive", 12 | "circular", 13 | "cyclic" 14 | ], 15 | "author": "d3x0r ", 16 | "contributors": [], 17 | "@std/esm": "cjs", 18 | "module": "lib/jsox.mjs", 19 | "main": "lib/jsox.js", 20 | "browser": "lib/jsox.es6.js.gz", 21 | "exports": { 22 | ".": { 23 | "require": "./lib/jsox.js", 24 | "module-sync": "./lib/jsox.mjs", 25 | "import": "./lib/jsox.mjs", 26 | "browser": "./lib/jsox.es6.js.gz" 27 | }, 28 | "./import.mjs": { 29 | "import": "./lib/import.mjs" 30 | }, 31 | "./import": { 32 | "import": "./lib/import.mjs" 33 | } 34 | }, 35 | "bin": "lib/cli.js", 36 | "files": [ 37 | "lib/jsox.js", 38 | "lib/jsox.d.ts", 39 | "lib/jsox.mjs", 40 | "lib/jsox.d.mts", 41 | "lib/jsox.min.js", 42 | "lib/jsox.min.mjs", 43 | "lib/jsox.min.js.gz", 44 | "lib/jsox.min.d.ts", 45 | "lib/jsox.min.mjs.gz", 46 | "lib/jsox.es6.js.gz", 47 | "lib/cli.js", 48 | "lib/require.js", 49 | "lib/import.mjs" 50 | ], 51 | "dependencies": {}, 52 | "devDependencies": { 53 | "core-js": "latest", 54 | "rollup": "latest", 55 | "eslint": "latest", 56 | "nyc": "latest", 57 | "mocha": "latest", 58 | "chai": "latest", 59 | "acorn": "latest", 60 | "lint-staged": "latest", 61 | "@rollup/plugin-buble": "latest", 62 | "@rollup/plugin-commonjs": "latest", 63 | "@rollup/plugin-node-resolve": "latest", 64 | "@rollup/plugin-strip": "latest", 65 | "@rollup/plugin-terser": "latest", 66 | "rollup-plugin-gzip": "latest" 67 | }, 68 | "nyc": { 69 | "ignore-class-method": [ 70 | "log" 71 | ], 72 | "reporter": [ 73 | "lcov", 74 | "text" 75 | ] 76 | }, 77 | "scripts": { 78 | "xprepack": "npm run test-lite", 79 | "lint": "eslint --cache .", 80 | "mocha-lite": "mocha --experimental-loader=./lib/import.mjs --require ./lib/require.js --require test/bootstrap/node", 81 | "mocha": "mocha --experimental-loader=./lib/import.mjs --require ./lib/require.js --require test/bootstrap/node --recursive", 82 | "nyc-lite": "nyc npm run mocha-lite", 83 | "nyc": "nyc npm run mocha-lite", 84 | "test-lite": "npm run lint && npm run build && npm run nyc-lite", 85 | "test": "npm run lint && npm run build && npm run nyc", 86 | "build": "node ./lib/cli.js -c package.jsox && rollup -c" 87 | }, 88 | "homepage": "http://npmjs.org/package/jsox/", 89 | "license": "MIT", 90 | "repository": { 91 | "type": "git", 92 | "url": "https://github.com/d3x0r/jsox" 93 | }, 94 | "arrayBuffer": { 95 | "0": 1963, 96 | "1": 47019, 97 | "2": 41515 98 | } 99 | } -------------------------------------------------------------------------------- /package.jsox: -------------------------------------------------------------------------------- 1 | // source file for package.json 2 | // use npm build to produce normalized package.json file. 3 | 4 | 5 | { 6 | name: "jsox", 7 | version: "1.2.124", 8 | description: "Java Script Object eXchange.", 9 | keywords: [ 10 | "jsox","json", 11 | "macro","template","class","recursive","circular","cyclic" 12 | ], 13 | author: "d3x0r ", 14 | contributors: [ 15 | ], 16 | "@std/esm": "cjs", 17 | module: "lib/jsox.mjs", 18 | main: "lib/jsox.js", 19 | browser: "lib/jsox.es6.js.gz", 20 | exports: { 21 | ".": { 22 | "require": "./lib/jsox.js", 23 | "module-sync": "./lib/jsox.mjs", 24 | "import": "./lib/jsox.mjs", 25 | "browser": "./lib/jsox.es6.js.gz" 26 | }, 27 | "./import.mjs": { 28 | "import": "./lib/import.mjs" 29 | }, 30 | "./import": { 31 | "import": "./lib/import.mjs" 32 | } 33 | }, 34 | bin: "lib/cli.js", 35 | files: [ 36 | "lib/jsox.js", 37 | "lib/jsox.d.ts", 38 | "lib/jsox.mjs", 39 | "lib/jsox.d.mts", 40 | "lib/jsox.min.js", 41 | "lib/jsox.min.mjs", 42 | "lib/jsox.min.js.gz", 43 | "lib/jsox.min.d.ts", 44 | "lib/jsox.min.mjs.gz", 45 | "lib/jsox.es6.js.gz", 46 | "lib/cli.js", 47 | "lib/require.js", 48 | "lib/import.mjs" 49 | ], 50 | dependencies: {}, 51 | 52 | devDependencies: { 53 | "core-js": "latest", 54 | rollup: "latest", 55 | eslint: "latest", 56 | nyc: "latest", 57 | mocha: "latest", 58 | chai: "latest", 59 | acorn: "latest", 60 | "lint-staged": "latest", 61 | // '/' is a comment character, and needs quotes 62 | "@rollup/plugin-buble": "latest", 63 | "@rollup/plugin-commonjs": "latest", 64 | "@rollup/plugin-node-resolve": "latest", 65 | "@rollup/plugin-strip": "latest", 66 | "@rollup/plugin-terser": "latest", 67 | "rollup-plugin-gzip": "latest" 68 | }, 69 | "nyc": { 70 | "ignore-class-method": [ 71 | "log" 72 | ], 73 | "reporter": [ 74 | "lcov", 75 | "text" 76 | ] 77 | }, 78 | 79 | scripts: { 80 | xprepack: "npm run test-lite", 81 | lint: "eslint --cache .", 82 | mocha-lite: "mocha --experimental-loader=./lib/import.mjs --require ./lib/require.js --require test/bootstrap/node", // --experimental-loader=./lib/import.mjs 83 | mocha: "mocha --experimental-loader=./lib/import.mjs --require ./lib/require.js --require test/bootstrap/node --recursive", // --experimental-loader=./lib/import.mjs 84 | nyc-lite: "nyc npm run mocha-lite", 85 | nyc: "nyc npm run mocha-lite", 86 | test-lite: "npm run lint && npm run build && npm run nyc-lite", 87 | test: "npm run lint && npm run build && npm run nyc", 88 | build: "node ./lib/cli.js -c package.jsox && rollup -c", 89 | }, 90 | homepage: "http://npmjs.org/package/jsox/", 91 | license: "MIT", 92 | repository: { 93 | type: "git", 94 | url: "https://github.com/d3x0r/jsox" 95 | }, 96 | arrayBuffer : u16[qwertyui] 97 | } -------------------------------------------------------------------------------- /test/1.2.108-nestedFinal.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | //const SACK=require("../.." ); 3 | //const JSOX = SACK.JSOX; 4 | const JSOX = require( ".." ); 5 | 6 | /* 7 | process.on("beforeExit", ()=>{ console.log( "EXITING" ) } ); 8 | process.on("uncaughtException",(a,b)=>{ 9 | console.log( "test", a, b ); 10 | } ); 11 | 12 | function describe(a,b) { return b() }; 13 | function it(a,b) { return b() }; 14 | let threw = null; 15 | function expect(a) { if( "function" === typeof a ) { try { threw = null; a(); } catch(err){threw=err}; } 16 | return ({ to: {deep:{ equal(b) { console.log( "did",a,"=",b); } } 17 | , equal(b) { console.log( "did",a,"=",b); } 18 | , throw(a) {console.log( "Success:error?", threw ) } } }); } 19 | */ 20 | 21 | 22 | describe('Added in 1.2.108', function () { 23 | 24 | it( 'Performs operations in the right order', function() { 25 | JSOX.reset(); 26 | 27 | const content = 'O{sub:s{inner:"VALUE",a:[1,2,3]},a:123,b:345,c:[5,6,7]}' 28 | const processed = []; 29 | const array = []; 30 | class SubO { 31 | inner = "value"; 32 | a = [1,2,3]; 33 | constructor(newval) { 34 | processed.push( "Constructed subO" ); 35 | if( newval ) this.inner = newval }; 36 | } 37 | class O { 38 | a = 0; 39 | sub = new SubO(); 40 | b = 0; 41 | c = array; 42 | constructor() { 43 | processed.push( "Constructed O" ); 44 | } 45 | } 46 | function fromJSOX( field, val ) { 47 | if( field ) { 48 | processed.push( [field, val, JSON.stringify(val)] ); 49 | if( field === "c" ) 50 | return this.c; 51 | else 52 | return val; 53 | } else { 54 | processed.push( "Final revive" ); 55 | this.c.push(8); 56 | return this; 57 | } 58 | 59 | } 60 | 61 | function subFromJSOX( field, val ) { 62 | if( field ) { 63 | processed.push( [field, val, JSON.stringify(val)] ); 64 | if( field === "c" ) 65 | return this.c; 66 | else 67 | return val; 68 | } else { 69 | processed.push( "Sub Final revive" ); 70 | return this; 71 | } 72 | 73 | } 74 | 75 | JSOX.fromJSOX( "s", SubO, subFromJSOX ); 76 | JSOX.fromJSOX( "O", O, fromJSOX ); 77 | const object = JSOX.parse( content ); 78 | 79 | processed.forEach( (val,idx)=>{ 80 | if( val instanceof Array ) if( "object" === typeof val[1] ) { 81 | val[1] = JSON.stringify(val[1]); 82 | processed[idx] = val.join(); 83 | } 84 | } ); 85 | 86 | //console.log( "Process:\n", processed.join("\n") ); 87 | expect( processed.join("\n") ).to.equal( `Constructed subO 88 | Constructed O 89 | Constructed subO 90 | inner,VALUE,"VALUE" 91 | a,[1,2,3],[] 92 | Sub Final revive 93 | sub,{"inner":"VALUE","a":[1,2,3]},{"inner":"VALUE","a":[1,2,3]} 94 | a,123,123 95 | b,345,345 96 | c,[],[] 97 | Final revive` ); 98 | expect( object ).to.deep.equal( { sub:new SubO("VALUE"),a:123,b:345,c:[5,6,7,8] } ); 99 | 100 | } ); 101 | 102 | } ); 103 | -------------------------------------------------------------------------------- /tests/testjson6.js: -------------------------------------------------------------------------------- 1 | 2 | //var JSON6 = require( "./json6.js" ); 3 | var JSON6 = require( '..' ); 4 | 5 | var lastval; 6 | var skip_out = true; 7 | var parser = JSON6.begin( (val)=>{ 8 | lastval = val; 9 | if( !skip_out ) 10 | console.log( "got value:", val ); 11 | } ); 12 | 13 | var complexSplit = `[ 14 | "db", 15 | { 16 | "_": { 17 | "#": "db", 18 | ">": { 19 | "j6bjv": 1502678337047 20 | } 21 | }, 22 | "j6bjr5rg": { 23 | "#": "j6bjzqK" 24 | } 25 | } 26 | ]`; 27 | 28 | var testOut = JSON.stringify( JSON.parse( complexSplit ) ); 29 | var testOut2 = JSON.stringify( JSON6.parse( complexSplit ) ); 30 | if( testOut != testOut2 ) 31 | console.log( "INITIAL FAIL" ); 32 | 33 | for( var n = 1; n < complexSplit.length; n++ ) { 34 | var a = complexSplit.substr( 0, n ); 35 | var b = complexSplit.substr( n ); 36 | //console.log( "parse:\n", JSON.stringify( a ), "\n", JSON.stringify(b)); 37 | if( !a || !b ) continue 38 | parser.write( a ); 39 | parser.write( b ); 40 | if( JSON.stringify( lastval ) != testOut ) 41 | console.log( "FAILED REASSEMBLY AT", n , '\n got:\n', JSON.stringify( lastval ), '\n Original:\n', testOut ); 42 | //console.log( "Tested:", JSON.stringify(a), JSON.stringify(b)); 43 | } 44 | 45 | skip_out = false; 46 | 47 | parser.write( '[]' ); 48 | parser.write( '[,]' ); 49 | parser.write( '[,,]' ); 50 | 51 | parser.write( `[ 52 | "db", 53 | { 54 | "_": { 55 | "#": "db", 56 | ">": { 57 | "j6bjv": 1502678337047 58 | } 59 | }, 60 | "j6bjr` ); 61 | 62 | parser.write( `5rg": { 63 | "#": "j6bjzqK" 64 | } 65 | } 66 | ]`); 67 | 68 | 69 | parser.write( "123\n" ); // this can no longer immediately preceed [ for streaming 70 | 71 | parser.write( "[\n null,\n null\n]" ); 72 | 73 | parser.write( '"Hello ' ); // a broken simple value string, results as 'Hello World!' 74 | parser.write( 'World!"' ); 75 | parser.write( '{ first: 1,' ); // a broken structure 76 | parser.write( ' second : 2 }' ); 77 | parser.write( '[1234,12'); // a broken array across a value 78 | parser.write( '34,1234]'); 79 | parser.write( '1234 456 789 123 523 '); // multiple single simple values that are numbers 80 | parser.write( '{a:1} {b:2} {c:3}'); // multiple objects 81 | 82 | parser.write( '1234' ); // this won't return immediately, there might be more numeric data. 83 | parser.write( '' ); // flush any pending numbers; if an object or array or string was split, throws an error; missing close. 84 | 85 | parser.write( '1234' ); 86 | parser.write( '5678 ' ); // at this point, the space will flush the number value '12345678' 87 | 88 | var start = Date.now(); 89 | var n; 90 | for( n = 0; n < 1000000; n++ ) { 91 | JSON6.parse( "{a:{b:{c:{d:123}}}}" ); 92 | // JSON6.parse( "{\"a\":{\"b\":{\"c\":{\"d\":123}}}}" ); 93 | JSON6.parse( '"Simple String value"' ); 94 | JSON6.parse( '123456789' ); 95 | } 96 | 97 | var end = Date.now(); 98 | console.log( "JSOX 1m in ", end-start ); 99 | 100 | var start = Date.now(); 101 | var n; 102 | for( n = 0; n < 1000000; n++ ) { 103 | JSON.parse( "{\"a\":{\"b\":{\"c\":{\"d\":123}}}}" ); 104 | JSON.parse( '"Simple String value"' ); 105 | JSON.parse( '123456789' ); 106 | } 107 | 108 | var end = Date.now(); 109 | console.log( "JSON 1m in ", end-start ); 110 | -------------------------------------------------------------------------------- /test/1.2.104-toFrom.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSOX = require( ".." ); 3 | 4 | /* 5 | process.on("beforeExit", ()=>{ console.log( "EXITING" ) } ); 6 | process.on("uncaughtException",(a,b)=>{ 7 | console.log( "test", a, b ); 8 | } ); 9 | 10 | function describe(a,b) { return b() }; 11 | function it(a,b) { return b() }; 12 | let threw = null; 13 | function expect(a) { if( "function" === typeof a ) { try { threw = null; a(); } catch(err){threw=err}; } 14 | return ({ to: {deep:{ equal(b) { console.log( "did",a,"=",b); } } 15 | , equal(b) { console.log( "did",a,"=",b); } 16 | , throw(a) {console.log( "Success:error?", threw ) } } }); } 17 | */ 18 | 19 | 20 | describe('Added in 1.2.104; toJSOX, fromJSOX', function () { 21 | it( "handles toJSOX and fromJSOX API", function() { 22 | const results = []; 23 | function parsed( obj ) { 24 | //console.log( "Obj?", obj ); 25 | results.push(obj); 26 | } 27 | 28 | function A() { 29 | this.a = 123; 30 | this.name = 'A'; 31 | } 32 | function B() { 33 | this.name = 'B'; 34 | } 35 | B.toString = function( stringifer ) { 36 | return `{b:${this.b}}`; 37 | } 38 | B.fromString = function( field,val ) { 39 | if( field ) return val; 40 | else return this; 41 | } 42 | function X() { 43 | this.x = new Map(); 44 | this.name = 'X'; 45 | } 46 | const now = new Date(); 47 | function Y() { 48 | this.y = now; 49 | this.name = 'Y'; 50 | } 51 | Y.toString = function( stringifer ) { 52 | return `{val:${this.val}}`; 53 | } 54 | Y.fromString = function( field,val ) { 55 | if( field ) return val; 56 | else return this; 57 | } 58 | const parser = JSOX.begin( parsed ); 59 | parser.fromJSOX( "X", X ); 60 | expect( function() { 61 | parser.fromJSOX( "X", X ); 62 | } ).to.throw( Error ); 63 | parser.fromJSOX( "Y", Y, Y.fromString ); 64 | JSOX.fromJSOX( "A", A ); 65 | expect( function() { 66 | JSOX.fromJSOX( "A", A ); 67 | } ).to.throw( Error ); 68 | JSOX.fromJSOX( "B", B, B.fromString ); 69 | 70 | parser.write( "A{a:555} B{b:134} X{x:map{field:value}} Y{val:555}" ); 71 | 72 | const expected = [ new A(), new B(), new X(), new Y() ]; 73 | 74 | expected[0].a = 555; 75 | expected[1].b = 134; 76 | expected[2].x.set( "field", "value" ); 77 | expected[3].val = 555; 78 | expect( results ).to.deep.equal( expected ); 79 | 80 | results.length = 0; 81 | 82 | const stringifier = JSOX.stringifier(); 83 | JSOX.toJSOX( "A", A ); 84 | JSOX.toJSOX( "B", B, B.toString ); 85 | stringifier.toJSOX( "X", X ); 86 | stringifier.toJSOX( "Y", Y, Y.toString ); 87 | 88 | const instance = stringifier.stringify( expected ); 89 | const simple = JSOX.stringify( expected ); 90 | 91 | expect( instance ).to.equal( '[A{a:555,name:A},B{b:134},X{name:X,x:map{field:value}},Y{val:555}]' ); 92 | expect( simple ).to.equal( `[A{a:555,name:A},B{b:134},{name:X,x:map{field:value}},{name:Y,val:555,y:${JSOX.stringify(now)}}]` ); 93 | } ); 94 | } ); 95 | -------------------------------------------------------------------------------- /test/jsoxStreamTest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSOX = require( ".." ); 3 | 4 | const parse = JSOX.parse; 5 | 6 | 7 | /* 8 | process.on("beforeExit", ()=>{ console.log( "EXITING" ) } ); 9 | process.on("uncaughtException",(a,b)=>{ 10 | console.log( "test", a, b ); 11 | } ); 12 | 13 | function describe(a,b) { return b() }; 14 | function it(a,b) { return b() }; 15 | let threw = null; 16 | function expect(a) { if( "function" === typeof a ) { try { threw = null; a(); } catch(err){threw=err}; } 17 | return ({ to: {deep:{ equal(a) { } } 18 | , throw(a) {console.log( "Success:error?", threw ) } } }); } 19 | */ 20 | 21 | 22 | describe('Stream testing', function () { 23 | it('Receives various values via `write`', function () { 24 | let results = []; 25 | const parser = JSOX.begin(function (obj) { 26 | //console.log( "Got value:", typeof obj, ":", obj ); 27 | results.push(obj); 28 | }); 29 | 30 | parser.write( '"This ' ); 31 | parser.write( 'is a Test"' ); 32 | 33 | parser.write( '[1234,12'); 34 | parser.write( '34,1234]'); 35 | 36 | parser.write( '[123,4'); 37 | parser.write( '56,78'); 38 | parser.write( '9,"abc","de'); 39 | parser.write( 'f","ghi"]'); 40 | 41 | 42 | parser.write( 'true false null undefined NaN Infinity' ); 43 | 44 | parser.write( "1 " ); 45 | parser.write( "123" ); 46 | parser.write( '"1"' ); 47 | 48 | parser.write( '{ a:12' ); 49 | parser.write( '34 }' ); 50 | 51 | parser.write( '{ long'); 52 | parser.write( 'key:1234 }' ); 53 | 54 | parser.write( '{ a:1234 }' ); 55 | //console.log( "4 objects..." ); 56 | parser.write( '{ a:1234 }{ b:34 }{c:1}{d:123}' ); 57 | //console.log( "got 4 objects?" ); 58 | 59 | expect(results).to.deep.equal([ 60 | 'This is a Test', 61 | [1234, 1234, 1234], 62 | [123, 456, 789, 'abc', 'def', 'ghi'], 63 | true, false, null, undefined, NaN, Infinity, 64 | 1, 65 | 123, 66 | '1', 67 | { a: 1234 }, 68 | { longkey: 1234 }, 69 | { a: 1234 }, 70 | { a: 1234 }, 71 | { b: 34 }, 72 | {c: 1}, 73 | {d: 123} 74 | ]); 75 | 76 | results = []; 77 | try { 78 | 79 | parser.reset(); 80 | } catch(err ) { console.log("Reset Failed?", err ) }; 81 | parser.write( '1_234 0x55_33_22_11 0x1234 ' ); 82 | expect(results).to.deep.equal([ 83 | 1234, 84 | 1429414417, 85 | 4660 86 | ]); 87 | 88 | parser.write( '123'); 89 | parser.write(); 90 | 91 | expect( function() { 92 | 93 | parser.write( '{a:123'); 94 | parser.write(); 95 | }).to.throw( Error ); 96 | parser.reset(); 97 | 98 | parser.write( '{a:"String'); 99 | parser.write( 'split Buffer"}' ); 100 | 101 | parser.write( '"String '); 102 | parser.write( 'coverage'); 103 | parser.write( ' test"' ); 104 | 105 | parser.write( '1' ); 106 | parser.write( '2' ); 107 | parser.write( '3' ); 108 | parser.write( '4' ); 109 | parser.write( '5' ); 110 | parser.write( ' ' ); 111 | 112 | // this is a test to trigger coverage. 113 | results = []; 114 | expect( function() { 115 | parser.write( '{ this is an error' ); 116 | }). to.throw( Error ); 117 | 118 | expect( function() { 119 | parser.write( '} 0 ' ); 120 | }). to.throw( Error ); 121 | 122 | //expect( function() { 123 | // parser.write( '} 0 ' ); 124 | //}).to.throw( Error ); 125 | parser.reset( ); 126 | parser.write( '"OK"' ); 127 | }); 128 | }); 129 | 130 | -------------------------------------------------------------------------------- /test/testjson6.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // var JSON6 = require( "./json6.js" ); 3 | const JSON6 = require( '..' ); 4 | 5 | describe('JSON streaming', function () { 6 | it('Parses multiple and split strings', function () { 7 | let lastval; 8 | let skip_out = true; 9 | const results = []; 10 | const parser = JSON6.begin(function (val) { 11 | lastval = val; 12 | if( !skip_out ) { 13 | //console.log( "got value:", val ); 14 | results.push(val); 15 | } 16 | }); 17 | 18 | const complexSplit = [ 19 | "db", 20 | { 21 | "_": { 22 | "#": "db", 23 | ">": { 24 | "j6bjv": 1502678337047 25 | } 26 | }, 27 | "j6bjr5rg": { 28 | "#": "j6bjzqK" 29 | } 30 | } 31 | ]; 32 | const complexSplitString = JSON.stringify(complexSplit); 33 | const testOut = complexSplitString; 34 | 35 | for( let n = 1; n < complexSplitString.length; n++ ) { 36 | const a = complexSplitString.substr( 0, n ); 37 | const b = complexSplitString.substr( n ); 38 | //console.log( "parse:\n", JSON.stringify( a ), "\n", JSON.stringify(b)); 39 | if( !a || !b ) continue; 40 | parser.write( a ); 41 | parser.write( b ); 42 | if( JSON.stringify( lastval ) != testOut ) { 43 | expect( 44 | false, 45 | "FAILED REASSEMBLY AT " + n + 46 | '\n got:\n' + JSON.stringify( lastval ) + 47 | '\n Original:\n' + testOut 48 | ).to.be.true; 49 | } 50 | //console.log( "Tested:", JSON.stringify(a), JSON.stringify(b)); 51 | } 52 | 53 | skip_out = false; 54 | 55 | parser.write( '[]' ); 56 | parser.write( '[,]' ); 57 | parser.write( '[,,]' ); 58 | 59 | const obj = [ 60 | "db", 61 | { 62 | "_": { 63 | "#": "db", 64 | ">": { 65 | "j6bjv": 1502678337047 66 | } 67 | }, 68 | "j6bjr5rg": { 69 | "#": "j6bjzqK" 70 | } 71 | } 72 | ]; 73 | const str = JSON.stringify(obj); 74 | const pos = str.indexOf('5rg'); 75 | 76 | 77 | parser.write(str.slice(0, pos)); 78 | parser.write(str.slice(pos)); 79 | 80 | 81 | parser.write( "123" ); 82 | 83 | parser.write( "[\n null,\n null\n]" ); 84 | 85 | parser.write( '"Hello ' ); // a broken simple value string, results as 'Hello World!' 86 | parser.write( 'World!"' ); 87 | parser.write( '{ first: 1,' ); // a broken structure 88 | parser.write( ' second : 2 }' ); 89 | parser.write( '[1234,12'); // a broken array across a value 90 | parser.write( '34,1234]'); 91 | parser.write( '1234 456 789 123 523'); // multiple single simple values that are numbers 92 | parser.write( '{a:1} {b:2} {c:3}'); // multiple objects 93 | 94 | parser.write( '1234' ); // this won't return immediately, there might be more numeric data. 95 | parser.write( '' ); // flush any pending numbers; if an object or array or string was split, throws an error; missing close. 96 | 97 | parser.write( '1234' ); 98 | parser.write( '5678 ' ); // at this point, the space will flush the number value '12345678' 99 | expect(results).to.deep.equal([ 100 | [], 101 | /* eslint-disable no-sparse-arrays */ 102 | [,], 103 | [,,], 104 | /* eslint-enable no-sparse-arrays */ 105 | obj, 106 | 123, 107 | [null, null], 108 | 'Hello World!', 109 | { first: 1, second : 2 }, 110 | [1234, 1234, 1234], 111 | 1234, 456, 789, 123, 523, 112 | {a: 1}, 113 | {b: 2}, 114 | {c: 3}, 115 | 1234, 116 | 12345678 117 | ]); 118 | }); 119 | }); 120 | -------------------------------------------------------------------------------- /test/benchmarks/json6ObjectArrays.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const JSON6 = require( "../../" ); 4 | const parse = JSON6.parse; 5 | 6 | // benchmark - needs some work; ended up somewhat divergent. 7 | describe('Objects/Arrays benchmarks', function () { 8 | this.timeout(25000); 9 | it('Benchmark nested objects', function () { 10 | let start = Date.now(); 11 | let result; 12 | for( let n = 0; n < 1000000; n++ ) { 13 | result = parse( "{\"a\":{\"b\":{\"c\":{\"d\":123}}}}" ); 14 | //parse( '"Simple String Value."' ); 15 | } 16 | let end = Date.now(); 17 | console.log( "1m in ", end-start ); 18 | expect(result).to.deep.equal({ 19 | a: {b: {c: {d: 123}}}} 20 | ); 21 | 22 | start = Date.now(); 23 | for( let n = 0; n < 1000000; n++ ) { 24 | result = parse( "[1,[2,[3,[4,5]]]]" ); 25 | //parse( '"Simple String Value."' ); 26 | } 27 | end = Date.now(); 28 | console.log( "1m in ", end-start ); 29 | expect(result).to.deep.equal([1,[2,[3,[4,5]]]]); 30 | 31 | 32 | // var translations = ["{\"a\":{\"b\":{\"c\":{\"d\":123}}}}","{\"a\":{\"b\":{\"c\":{\"d\":123}}}}","{\"a\":{\"b\":{\"c\":{\"d\":123}}}}","{\"a\":{\"b\":{\"c\":{\"d\":123}}}}"]; 33 | // var ntrans = 0; 34 | 35 | start = end; 36 | for( let n = 0; n < 5000000; n++ ) { 37 | result = JSON.parse( "{\"a\":{\"b\":{\"c\":{\"d\":123}}}}" ); 38 | //JSON.parse( translations[ntrans] ); 39 | //ntrans = (ntrans+1)&3; 40 | } 41 | end = Date.now(); 42 | console.log( "1m in ", end-start ); 43 | expect(result).to.deep.equal({ 44 | a: {b: {c: {d: 123}}} 45 | }); 46 | }); 47 | it('Benchmark nested array', function () { 48 | const start = Date.now(); 49 | let result; 50 | for( let n = 0; n < 5000000; n++ ) { 51 | result = JSON.parse( "[1,[2,[3,[4,5]]]]" ); 52 | //parse( '"Simple String Value."' ); 53 | } 54 | const end = Date.now(); 55 | console.log( "1m in ", end-start ); 56 | expect(result).to.deep.equal( 57 | [1, [2, [3, [4, 5]]]] 58 | ); 59 | }); 60 | // benchmark - needs some work; ended up somewhat divergent. 61 | it('Benchmark nested object with numeric keys', function () { 62 | const varObjects = []; 63 | for( let n = 0; n < 100000; n++ ) { 64 | varObjects.push( 65 | '{"a' + n + '":{"b' + n + '":{"c' + n + '":{"d' + n + '":123}}}}' 66 | ); 67 | } 68 | 69 | /* 70 | var varStrings = []; 71 | for( var n = 0; n < 100000; n++ ) { 72 | varStrings.push( `"SImple STring Value ${n}"` ); 73 | } 74 | 75 | var varNumbers = []; 76 | for( var n = 0; n < 100000; n++ ) { 77 | varNumbers.push( `${n}` ); 78 | } 79 | */ 80 | 81 | 82 | let start = Date.now(); 83 | for( let n = 0; n < 500000; n++ ) { 84 | parse( varObjects[n % 100000] ); 85 | // parse( varStrings[n%100000] ); 86 | // parse( varNumbers[n%100000] ); 87 | // parse( "{\"a\":{\"b\":{\"c\":{\"d\":123}}}}" ); 88 | // parse( '"Simple String value"' ); 89 | // parse( '123456789' ); 90 | } 91 | 92 | let end = Date.now(); 93 | console.log( "1m in ", end-start ); 94 | 95 | 96 | start = end; 97 | for( let n = 0; n < 500000; n++ ) { 98 | JSON.parse( varObjects[n % 100000] ); 99 | // JSON.parse( varStrings[n%100000] ); 100 | // JSON.parse( varNumbers[n%100000] ); 101 | /* JSON.parse( "{\"a\":{\"b\":{\"c\":{\"d\":123}}}}" );*/ 102 | // JSON.parse( '"Simple String value"' ); 103 | // JSON.parse( '123456789' ); 104 | } 105 | end = Date.now(); 106 | console.log( "1m in ", end - start ); 107 | expect(true).to.be.true; 108 | }); 109 | }); 110 | -------------------------------------------------------------------------------- /test/1.2.108-nestedFinalInstanced.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | //const SACK=require("../.." ); 3 | //const JSOX = SACK.JSOX; 4 | const JSOX = require( ".." ); 5 | 6 | /* 7 | process.on("beforeExit", ()=>{ console.log( "EXITING" ) } ); 8 | process.on("uncaughtException",(a,b)=>{ 9 | console.log( "test", a, b ); 10 | } ); 11 | 12 | function describe(a,b) { return b() }; 13 | function it(a,b) { return b() }; 14 | let threw = null; 15 | function expect(a) { if( "function" === typeof a ) { try { threw = null; a(); } catch(err){threw=err}; } 16 | return ({ to: {deep:{ equal(b) { console.log( "did",a,"=",b); } } 17 | , equal(b) { console.log( "did",a,"=",b); } 18 | , throw(a) {console.log( "Success:error?", threw ) } } }); } 19 | */ 20 | 21 | 22 | describe('Added in 1.2.108', function () { 23 | 24 | 25 | 26 | it( 'Performs operations in the right order (on instance)', function() { 27 | JSOX.reset(); 28 | const content = 'O{sub:s{inner:"VALUE",a:[1,2,3]},a:123,b:345,c:[5,6,7]}' 29 | const processed = []; 30 | const array = []; 31 | class SubO { 32 | inner = "value"; 33 | a=[1,2,3]; 34 | constructor(newval) { 35 | processed.push( "Constructed subO" ); 36 | if( newval ) this.inner = newval }; 37 | } 38 | class O { 39 | a = 0; 40 | sub = new SubO(); 41 | b = 0; 42 | c = array; 43 | constructor() { 44 | processed.push( "Constructed O" ); 45 | } 46 | } 47 | function fromJSOX( field, val ) { 48 | if( field ) { 49 | processed.push( [field, val, JSON.stringify(val)] ); 50 | if( field === "c" ) 51 | return this.c; 52 | else 53 | return val; 54 | } else { 55 | processed.push( "Final revive" ); 56 | this.c.push(8); 57 | return this; 58 | } 59 | 60 | } 61 | 62 | function subFromJSOX( field, val ) { 63 | if( field ) { 64 | processed.push( [field, val, JSON.stringify(val)] ); 65 | if( field === "c" ) 66 | return this.c; 67 | else 68 | return val; 69 | } else { 70 | processed.push( "Sub Final revive" ); 71 | return this; 72 | } 73 | 74 | } 75 | 76 | const parser = JSOX.begin( result ); 77 | 78 | parser.fromJSOX( "s", SubO, subFromJSOX ); 79 | parser.fromJSOX( "O", O, fromJSOX ); 80 | let object = null 81 | parser.write( content ); 82 | 83 | function result( obj ) { 84 | object = obj; 85 | //console.log( "Got callback?", obj, processed ); 86 | processed.forEach( (val,idx)=>{ 87 | if( val instanceof Array ) if( "object" === typeof val[1] ) { 88 | val[1] = JSON.stringify(val[1]); 89 | processed[idx] = val.join(); 90 | } 91 | } ); 92 | 93 | } 94 | 95 | //console.log( "Process:\n", processed.join("\n") ); 96 | expect( processed.join("\n") ).to.equal( `Constructed subO 97 | Constructed O 98 | Constructed subO 99 | inner,VALUE,"VALUE" 100 | a,[1,2,3],[] 101 | Sub Final revive 102 | sub,{"inner":"VALUE","a":[1,2,3]},{"inner":"VALUE","a":[1,2,3]} 103 | a,123,123 104 | b,345,345 105 | c,[],[] 106 | Final revive` ); 107 | expect( object ).to.deep.equal( { sub:new SubO("VALUE"),a:123,b:345,c:[5,6,7,8] } ); 108 | 109 | } ); 110 | 111 | } ); 112 | -------------------------------------------------------------------------------- /tests/data/testReferenceRevive.jsox: -------------------------------------------------------------------------------- 1 | 2 | 3 | { 4 | data: { 5 | data: { 6 | groups: [{ 7 | captain: { 8 | children: [], 9 | created: 2019-05-16T14:05:10-07:00, 10 | name: "Tom", 11 | parents: [{ 12 | children: [ref["data", "data", "groups", 0, "captain"], { 13 | children: [], 14 | created: 2019-05-16T14:05:10-07:00, 15 | name: "Alice", 16 | parents: [], 17 | siblings: [ref["data", "data", "groups", 0, "captain"], { 18 | children: [], 19 | created: 2019-05-16T14:05:10-07:00, 20 | name: "Bob", 21 | parents: [], 22 | siblings: [ref["data", "data", "groups", 0, "captain"] 23 | , ref["data", "data", "groups", 0, "captain", "parents", 0, "children", 1]], 24 | spice: [], 25 | user_id: "YmZVBB7c1T2D9idyWmc75mWMBJNE$O6u_xOaGp4bwAk=" 26 | }], 27 | spice: [], 28 | user_id: "6Q6Q8Ca1fCblmGhZYEzrC_Cbe5qxmyoGVjo1PrBImw0=" 29 | }, ref["data", "data", "groups", 0, "captain", "parents", 0, "children", 1, "siblings", 1]], 30 | created: 2019-05-16T14:05:10-07:00, 31 | name: "Jerrie", 32 | parents: [], 33 | siblings: [], 34 | spice: [{ 35 | children: [ref["data", "data", "groups", 0, "captain"] 36 | , ref["data", "data", "groups", 0, "captain", "parents", 0, "children", 1] 37 | , ref["data", "data", "groups", 0, "captain", "parents", 0, "children", 1, "siblings", 1]], 38 | created: 2019-05-16T14:05:10-07:00, 39 | name: "Harry", 40 | parents: [], 41 | siblings: [], 42 | spice: [], 43 | user_id: "nopYfH9gfEx$XE0nrT5YiRNBc5GeJDcEB031vPLERaI=" 44 | }, ref["data", "data", "groups", 0, "captain", "parents", 0]], 45 | user_id: "L$zZTtjNH6DngoL8tWz7fn6QDKsEd3GpxcCAZIcKmOQ=" 46 | }, ref["data", "data", "groups", 0, "captain", "parents", 0, "spice", 0]], 47 | siblings: [ref["data", "data", "groups", 0, "captain", "parents", 0, "children", 1] 48 | , ref["data", "data", "groups", 0, "captain", "parents", 0, "children", 1, "siblings", 1]], 49 | spice: [], 50 | user_id: "jw56VioAX4E0VSalmDzRyv68gTjqUZp8PmESMZjJVsc=" 51 | }, 52 | members: { 53 | children: [], 54 | created: 2019-05-16T14:05:10-07:00, 55 | name: "Barb", 56 | parents: [{ 57 | children: [ref["data", "data", "groups", 0, "members"]], 58 | created: 2019-05-16T14:05:10-07:00, 59 | name: "Monica", 60 | parents: [], 61 | siblings: [], 62 | spice: [], 63 | user_id: "ObPEfWqvehsAStM7HoMNiEdbGSCh2sbU6DmzlVNcevs=" 64 | }], 65 | siblings: [{ 66 | children: [], 67 | created: 2019-05-16T14:05:10-07:00, 68 | name: "Nick", 69 | parents: [], 70 | siblings: [], 71 | spice: [], 72 | user_id: "GAmo6jep_ZCxWG35m_QhcUN_UR1u5Q0za$Zbe2SqT68=" 73 | }], 74 | spice: [], 75 | user_id: "YFLkultOF4hJgODgA56AbXMnYX$63VzuPcTS6vvH318=" 76 | }, 77 | name: "Group 1" 78 | }], 79 | tick: 2019-05-16T05:02:52-07:00, 80 | users: [ref["data", "data", "groups", 0, "captain"], ref["data", "data", "groups", 0, "captain", "parents", 0, "children", 1], ref["data", "data", "groups", 0, "captain", "parents", 0, "children", 1, "siblings", 1], ref["data", "data", "groups", 0, "captain", "parents", 0], ref["data", "data", "groups", 0, "captain", "parents", 0, "spice", 0], ref["data", "data", "groups", 0, "members"], ref["data", "data", "groups", 0, "members", "siblings", 0], ref["data", "data", "groups", 0, "members", "parents", 0]] 81 | }, 82 | nonce: null 83 | }, 84 | id: "7pXRYvN577MMLA1WS7laY42Hb_USTfRpz5JAVujsVK4=" 85 | } -------------------------------------------------------------------------------- /test/json6BadTest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSON6 = require( ".." ); 3 | 4 | const parse = JSON6.parse; 5 | let o; 6 | 7 | describe('Bad tests', function () { 8 | 9 | it('space error "tr "', function () { 10 | o = parse( "tr " ); 11 | expect(o).to.equal("tr"); 12 | } ); 13 | 14 | it('space error "[tr ]"', function () { 15 | o = parse( "[tr ]" ); 16 | expect(o).to.deep.equal(["tr"]); 17 | } ); 18 | 19 | it('space error "{a:tr }"', function () { 20 | o = parse( "{a:tr }" ); 21 | //console.log( "got back:", o ); 22 | expect(o).to.deep.equal({a:"tr"}); 23 | } ); 24 | 25 | 26 | it('Unquoted space in identifier', function () { 27 | expect(function () { 28 | o = parse( "{ a b:1 }" ); 29 | //console.log( "got back:", o ); 30 | }).to.throw(Error); 31 | }); 32 | 33 | it('Missing colon array?', function () { 34 | expect(function () { 35 | o = parse( "{ a[3], b:1 }" ); 36 | //console.log( "got back:", o ); 37 | }).to.throw(Error); 38 | }); 39 | 40 | it('Missing colon object?', function () { 41 | expect(function () { 42 | o = parse( "{ a{c:3}, b:1 }" ); 43 | //console.log( "got back:", o ); 44 | }).to.throw(Error); 45 | }); 46 | 47 | it('String unquoted?', function () { 48 | expect(function () { 49 | o = parse( "{ a : no quote }" ); 50 | //console.log( "got back:", o ); 51 | }).to.throw(Error); 52 | }); 53 | 54 | it('Throws with colon in array', function () { 55 | expect(function () { 56 | parse( "[:]" ); 57 | }).to.throw(Error); 58 | }); 59 | 60 | /* JSOX ':' at this level allows redefinition of classes 61 | it('Throws with colon outside objects', function () { 62 | expect(function () { 63 | parse( ":" ); 64 | }).to.throw(Error); 65 | }); 66 | */ 67 | 68 | it('Throws with comma outside objects', function () { 69 | expect(function () { 70 | parse( "," ); 71 | }).to.throw(Error, /excessive commas|fault while parsing/); 72 | }); 73 | 74 | it('Throws with curly bracket outside objects', function () { 75 | expect(function () { 76 | parse( "}" ); 77 | }).to.throw(Error); 78 | }); 79 | 80 | /* 81 | TODO 82 | this is sort of an error, if 'no quote' isn't defined; but right now the parser accepts it until the reviver... (becomes classname in value) 83 | it('Array after string?', function () { 84 | expect(function () { 85 | o = parse( "{ a : 'no quote' [1] }" ); 86 | console.log( "got back:", o ); 87 | }).to.throw(Error); 88 | }); 89 | */ 90 | 91 | it('comma after object field and : ', function () { 92 | expect(function () { 93 | o = parse( "{a:,}" ); 94 | }).to.throw(Error); 95 | }); 96 | 97 | it('object close after object field and : ', function () { 98 | expect(function () { 99 | o = parse( "{a:}" ); 100 | console.log( "got back:", o ); 101 | }).to.throw(Error); 102 | }); 103 | 104 | it('bad hex escape : ', function () { 105 | expect(function () { 106 | o = parse( "'\\x1Z'" ); 107 | console.log( "got back:", o ); 108 | }).to.throw(Error); 109 | }); 110 | 111 | it('bad unicode escape : ', function () { 112 | expect(function () { 113 | o = parse( "'\\u01Zz'" ); 114 | console.log( "got back:", o ); 115 | }).to.throw(Error); 116 | }); 117 | 118 | 119 | it('throws with quoted field name after no comma : ', function () { 120 | expect(function () { 121 | o = parse( '{ "a": { "a": 5 } "abc": { "a": 5 } }' ); 122 | }).to.throw(Error,/String unexpected|outside any object, got colon out of string /); 123 | }); 124 | 125 | it('throws with unquoted field name after no comma: ', function () { 126 | expect(function () { 127 | o = parse( '{ "a": { "a": 5 } abc: { "a": 5 } }' ); 128 | }).to.throw(Error,/String unexpected|outside any object, got colon out of string/); 129 | }); 130 | 131 | 132 | 133 | }); 134 | -------------------------------------------------------------------------------- /tests/srg_prefix.js: -------------------------------------------------------------------------------- 1 | var JSOX = require( ".." ); 2 | 3 | const jsox = "u8['AQAAAAAAAAAAAAAAiQAAAAAAAACLAACAAAAAAICAAIABAAAAiwAAAAEAAAAAgAAAAQAAAIiAAIABAAAAggAAgAAAAAALAAAAAAAAAAoAAAABAAAAgoAAAAAAAAADgAAAAQAAAIuAAAABAAAACwAAgAEAAACKAACAAQAAAIEAAIAAAAAAgQAAgAAAAAAIAACAAAAAAIMAAAAAAAAAA4AAgAEAAACIgACAAAAAAIgAAIABAAAAAIAAAAAAAACCgACA/wAAANAAAAAFAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAAOAAAABAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAK/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBIQVNFOiVkABEACgAREREAAAAABQAAAAAAAAkAAAAACwAAAAAAAAAAEQAPChEREQMKBwABEwkLCwAACQYLAAALAAYRAAAAERERAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAABEACgoREREACgAAAgAJCwAAAAkACwAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAwAAAAACQwAAAAAAAwAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAADQAAAAQNAAAAAAkOAAAAAAAOAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAA8AAAAADwAAAAAJEAAAAAAAEAAAEAAAEgAAABISEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAEhISAAAAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAAAAAAAAAACgAAAAAKAAAAAAkLAAAAAAALAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAwAAAAADAAAAAAJDAAAAAAADAAADAAALSsgICAwWDB4AChudWxsKQAtMFgrMFggMFgtMHgrMHggMHgAaW5mAElORgBuYW4ATkFOADAxMjM0NTY3ODlBQkNERUYuAFQhIhkNAQIDEUscDBAECx0SHidobm9wcWIgBQYPExQVGggWBygkFxgJCg4bHyUjg4J9JiorPD0+P0NHSk1YWVpbXF1eX2BhY2RlZmdpamtscnN0eXp7fABJbGxlZ2FsIGJ5dGUgc2VxdWVuY2UARG9tYWluIGVycm9yAFJlc3VsdCBub3QgcmVwcmVzZW50YWJsZQBOb3QgYSB0dHkAUGVybWlzc2lvbiBkZW5pZWQAT3BlcmF0aW9uIG5vdCBwZXJtaXR0ZWQATm8gc3VjaCBmaWxlIG9yIGRpcmVjdG9yeQBObyBzdWNoIHByb2Nlc3MARmlsZSBleGlzdHMAVmFsdWUgdG9vIGxhcmdlIGZvciBkYXRhIHR5cGUATm8gc3BhY2UgbGVmdCBvbiBkZXZpY2UAT3V0IG9mIG1lbW9yeQBSZXNvdXJjZSBidXN5AEludGVycnVwdGVkIHN5c3RlbSBjYWxsAFJlc291cmNlIHRlbXBvcmFyaWx5IHVuYXZhaWxhYmxlAEludmFsaWQgc2VlawBDcm9zcy1kZXZpY2UgbGluawBSZWFkLW9ubHkgZmlsZSBzeXN0ZW0ARGlyZWN0b3J5IG5vdCBlbXB0eQBDb25uZWN0aW9uIHJlc2V0IGJ5IHBlZXIAT3BlcmF0aW9uIHRpbWVkIG91dABDb25uZWN0aW9uIHJlZnVzZWQASG9zdCBpcyBkb3duAEhvc3QgaXMgdW5yZWFjaGFibGUAQWRkcmVzcyBpbiB1c2UAQnJva2VuIHBpcGUASS9PIGVycm9yAE5vIHN1Y2ggZGV2aWNlIG9yIGFkZHJlc3MAQmxvY2sgZGV2aWNlIHJlcXVpcmVkAE5vIHN1Y2ggZGV2aWNlAE5vdCBhIGRpcmVjdG9yeQBJcyBhIGRpcmVjdG9yeQBUZXh0IGZpbGUgYnVzeQBFeGVjIGZvcm1hdCBlcnJvcgBJbnZhbGlkIGFyZ3VtZW50AEFyZ3VtZW50IGxpc3QgdG9vIGxvbmcAU3ltYm9saWMgbGluayBsb29wAEZpbGVuYW1lIHRvbyBsb25nAFRvbyBtYW55IG9wZW4gZmlsZXMgaW4gc3lzdGVtAE5vIGZpbGUgZGVzY3JpcHRvcnMgYXZhaWxhYmxlAEJhZCBmaWxlIGRlc2NyaXB0b3IATm8gY2hpbGQgcHJvY2VzcwBCYWQgYWRkcmVzcwBGaWxlIHRvbyBsYXJnZQBUb28gbWFueSBsaW5rcwBObyBsb2NrcyBhdmFpbGFibGUAUmVzb3VyY2UgZGVhZGxvY2sgd291bGQgb2NjdXIAU3RhdGUgbm90IHJlY292ZXJhYmxlAFByZXZpb3VzIG93bmVyIGRpZWQAT3BlcmF0aW9uIGNhbmNlbGVkAEZ1bmN0aW9uIG5vdCBpbXBsZW1lbnRlZABObyBtZXNzYWdlIG9mIGRlc2lyZWQgdHlwZQBJZGVudGlmaWVyIHJlbW92ZWQARGV2aWNlIG5vdCBhIHN0cmVhbQBObyBkYXRhIGF2YWlsYWJsZQBEZXZpY2UgdGltZW91dABPdXQgb2Ygc3RyZWFtcyByZXNvdXJjZXMATGluayBoYXMgYmVlbiBzZXZlcmVkAFByb3RvY29sIGVycm9yAEJhZCBtZXNzYWdlAEZpbGUgZGVzY3JpcHRvciBpbiBiYWQgc3RhdGUATm90IGEgc29ja2V0AERlc3RpbmF0aW9uIGFkZHJlc3MgcmVxdWlyZWQATWVzc2FnZSB0b28gbGFyZ2UAUHJvdG9jb2wgd3JvbmcgdHlwZSBmb3Igc29ja2V0AFByb3RvY29sIG5vdCBhdmFpbGFibGUAUHJvdG9jb2wgbm90IHN1cHBvcnRlZABTb2NrZXQgdHlwZSBub3Qgc3VwcG9ydGVkAE5vdCBzdXBwb3J0ZWQAUHJvdG9jb2wgZmFtaWx5IG5vdCBzdXBwb3J0ZWQAQWRkcmVzcyBmYW1pbHkgbm90IHN1cHBvcnRlZCBieSBwcm90b2NvbABBZGRyZXNzIG5vdCBhdmFpbGFibGUATmV0d29yayBpcyBkb3duAE5ldHdvcmsgdW5yZWFjaGFibGUAQ29ubmVjdGlvbiByZXNldCBieSBuZXR3b3JrAENvbm5lY3Rpb24gYWJvcnRlZABObyBidWZmZXIgc3BhY2UgYXZhaWxhYmxlAFNvY2tldCBpcyBjb25uZWN0ZWQAU29ja2V0IG5vdCBjb25uZWN0ZWQAQ2Fubm90IHNlbmQgYWZ0ZXIgc29ja2V0IHNodXRkb3duAE9wZXJhdGlvbiBhbHJlYWR5IGluIHByb2dyZXNzAE9wZXJhdGlvbiBpbiBwcm9ncmVzcwBTdGFsZSBmaWxlIGhhbmRsZQBSZW1vdGUgSS9PIGVycm9yAFF1b3RhIGV4Y2VlZGVkAE5vIG1lZGl1bSBmb3VuZABXcm9uZyBtZWRpdW0gdHlwZQBObyBlcnJvciBpbmZvcm1hdGlvbg==']" 4 | 5 | console.log( "Thing:", JSOX.parse( jsox ) ); -------------------------------------------------------------------------------- /tests/data/tasks.jsox: -------------------------------------------------------------------------------- 1 | task{ name,args,program,path,suspend,exclusive,restart,assumeReadyIn,minLaunchTime,MaxLauncherPerMinTime,require } 2 | 3 | { 4 | node : "H:/dev2/nodejs/node.exe", 5 | tasks: [ 6 | //suspend startup 7 | // service is another keyword that should be implememtned 8 | 9 | //[Remote] task #create a new task referenced by name 10 | 11 | task{ "Core" 12 | , ["--inspect", "--debug=5858", "main.js"] 13 | , ref["node"] 14 | , ".." 15 | , false , false , true , 2500, 250 , 1 16 | , null 17 | } 18 | ,task{ "WebServer" 19 | , ["--inspect", "--debug=5866", "../common/myNode.js"] 20 | , ref["node"] 21 | , "../node/webInterface" 22 | , false, false, true, 2500, 250, 1 23 | , [ "Core" ] 24 | } 25 | , { name: "userDatabase" 26 | , args : ["--inspect", "--debug=5859", "../common/myNode.js"] 27 | , program:ref["node"] 28 | , path : "../node/userDatabase" 29 | , suspend: false 30 | , exclusive : false 31 | , restart : true 32 | , assumeReadyIn: 2500 33 | , minLaunchTime : 250 34 | , maxLaunchsPerMinTime : 1 35 | , require : [ "Core" ] 36 | } 37 | , { name: "Auth0" 38 | , args : ["--inspect", "--debug=5860", "../common/myNode.js"] 39 | , program:ref["node"] 40 | , path : "../node/Auth0" 41 | , suspend: false 42 | , exclusive : false 43 | , restart : true 44 | , assumeReadyIn: 2500 45 | , minLaunchTime : 250 46 | , maxLaunchsPerMinTime : 1 47 | , require : [ "Core" ] 48 | } 49 | , { name: "chatAdmin" 50 | , args : ["--inspect", "--debug=5861", "../common/myNode.js"] 51 | , program:ref["node"] 52 | , path : "../node/chatAdmin" 53 | , suspend: false 54 | , exclusive : false 55 | , restart : true 56 | , assumeReadyIn: 2500 57 | , minLaunchTime : 250 58 | , maxLaunchsPerMinTime : 1 59 | , require : [ "Core" ] 60 | } 61 | 62 | , { name: "chatCore" 63 | , args : ["--inspect", "--debug=5862", "../common/myNode.js"] 64 | , program:ref["node"] 65 | , path : "../node/chatCore" 66 | , suspend: false 67 | , exclusive : false 68 | , restart : true 69 | , assumeReadyIn: 2500 70 | , minLaunchTime : 250 71 | , maxLaunchsPerMinTime : 1 72 | , require : [ "Core" ] 73 | } 74 | 75 | , { name: "groupCore" 76 | , args : ["--inspect", "--debug=5863", "../common/myNode.js"] 77 | , program:ref["node"] 78 | , path : "../node/groupCore" 79 | , suspend: false 80 | , exclusive : false 81 | , restart : true 82 | , assumeReadyIn: 2500 83 | , minLaunchTime : 250 84 | , maxLaunchsPerMinTime : 1 85 | , require : [ "Core" ] 86 | } 87 | 88 | , { name: "chatProtocol" 89 | , args : ["--inspect", "--debug=5864", "../common/myNode.js"] 90 | , program : "H:/dev2/nodejs/node.exe" 91 | , path : "../node/chatProtocol" 92 | , suspend: false 93 | , exclusive : false 94 | , restart : true 95 | , assumeReadyIn: 2500 96 | , minLaunchTime : 250 97 | , maxLaunchsPerMinTime : 1 98 | , require : [ "Core" ] 99 | } 100 | 101 | , { name: "chatStorage" 102 | , args : ["--inspect", "--debug=5865", "../common/myNode.js"] 103 | , program : "H:/dev2/nodejs/node.exe" 104 | , path : "../node/chatProtocol" 105 | , suspend: false 106 | , exclusive : false 107 | , restart : true 108 | , assumeReadyIn: 2500 109 | , minLaunchTime : 250 110 | , maxLaunchsPerMinTime : 1 111 | , require : [ "Core" ] 112 | } 113 | 114 | ] 115 | } -------------------------------------------------------------------------------- /test/benchmarks/json6NumberTest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const JSON = require( "../../" ); 4 | 5 | describe('Number tests (with benchmarking)', function () { 6 | this.timeout(10000); 7 | it('Negative decimal', function () { 8 | console.log( JSON.parse( "-1234" ) ); 9 | const start = Date.now(); 10 | let result; 11 | for( let m = 0; m < 40; m++ ) 12 | for( let n = 0; n < 100000; n++ ) 13 | result = JSON.parse( "-1234" ); 14 | 15 | console.log( "took:", Date.now() - start ); 16 | expect(result).to.equal(-1234); 17 | }); 18 | 19 | it('Negative decimal (single loop)', function () { 20 | console.log( JSON.parse( "-1234" ) ); 21 | const start = Date.now(); 22 | let result; 23 | for( let n = 0; n < 2000000; n++ ) 24 | result = JSON.parse( "-1234" ); 25 | console.log( "took:", Date.now() - start ); 26 | expect(result).to.equal(-1234); 27 | }); 28 | 29 | it('Decimal', function () { 30 | console.log( JSON.parse( "1234" ) ); 31 | const start = Date.now(); 32 | let result; 33 | for( let m = 0; m < 40; m++ ) 34 | for( let n = 0; n < 100000; n++ ) 35 | result = JSON.parse( "1234" ); 36 | console.log( "took:", Date.now() - start ); 37 | expect(result).to.equal(1234); 38 | }); 39 | 40 | it('Decimal (single loop)', function () { 41 | console.log( JSON.parse( "1234" ) ); 42 | const start = Date.now(); 43 | let result; 44 | for( let n = 0; n < 2000000; n++ ) 45 | result = JSON.parse( "1234" ); 46 | console.log( "took:", Date.now() - start ); 47 | expect(result).to.equal(1234); 48 | }); 49 | 50 | it('Simple object with number', function () { 51 | console.log( JSON.parse( "{a:1234}" ) ); 52 | const start = Date.now(); 53 | let result; 54 | for( let n = 0; n < 2000000; n++ ) 55 | result = JSON.parse( "{a:1234}" ); 56 | console.log( "took:", Date.now() - start ); 57 | expect(result).to.deep.equal({ 58 | a: 1234 59 | }); 60 | }); 61 | 62 | it('Simple object with negative number', function () { 63 | console.log( JSON.parse( "{a:-1234}" ) ); 64 | const start = Date.now(); 65 | let result; 66 | for( let n = 0; n < 2000000; n++ ) 67 | result = JSON.parse( "{a:-1234}" ); 68 | console.log( "took:", Date.now() - start ); 69 | expect(result).to.deep.equal({ 70 | a: -1234 71 | }); 72 | }); 73 | 74 | it('Simple array with number', function () { 75 | console.log( JSON.parse( "[1234]" ) ); 76 | const start = Date.now(); 77 | let result; 78 | for( let n = 0; n < 2000000; n++ ) 79 | result = JSON.parse( "[1234]" ); 80 | console.log( "took:", Date.now() - start ); 81 | expect(result).to.deep.equal([1234]); 82 | }); 83 | 84 | it('Simple array with negative number', function () { 85 | console.log( JSON.parse( "[-1234]" ) ); 86 | const start = Date.now(); 87 | let result; 88 | for( let n = 0; n < 2000000; n++ ) 89 | result = JSON.parse( "[-1234]" ); 90 | console.log( "took:", Date.now() - start ); 91 | expect(result).to.deep.equal([-1234]); 92 | }); 93 | 94 | 95 | it('Simple object with decimal', function () { 96 | console.log( JSON.parse( "{a:0.1234}" ) ); 97 | const start = Date.now(); 98 | let result; 99 | for( let n = 0; n < 1000000; n++ ) 100 | result = JSON.parse( "{a:0.1234}" ); 101 | console.log( "took:", Date.now() - start ); 102 | expect(result).to.deep.equal({a: 0.1234}); 103 | }); 104 | 105 | it('Simple object with negative octal treated as decimal', function () { 106 | console.log( JSON.parse( "{a:-01234}" ) ); 107 | const start = Date.now(); 108 | let result; 109 | for( let n = 0; n < 1009000; n++ ) 110 | result = JSON.parse( "{a:-01234}" ); 111 | console.log( "took:", Date.now() - start ); 112 | expect(result).to.deep.equal({a: -1234}); 113 | }); 114 | 115 | it('Simple array with negative hexadecimal', function () { 116 | console.log( JSON.parse( "[-0x1234]" ) ); 117 | const start = Date.now(); 118 | let result; 119 | for( let m = 0; m < 20; m++ ) 120 | for( let n = 0; n < 100000; n++ ) 121 | result = JSON.parse( "[-0x1234]" ); 122 | console.log( "took:", Date.now() - start ); 123 | expect(result).to.deep.equal([-4660]); 124 | }); 125 | 126 | // console.log( "Waiting forever..." ); 127 | // function wait() { setTimeout( wait, 2000 ) } 128 | // wait(); 129 | }); 130 | -------------------------------------------------------------------------------- /tests/data/test_1.2.114.jsox: -------------------------------------------------------------------------------- 1 | {accruals:{activities:[ {accrual_activity_id:L529UERozXtvH_0M,groups:[],inputs:[],name:AM} 2 | ,{accrual_activity_id:OdbXJT5h$sX_8lLD,groups:[],inputs:[],name:Moonlight} 3 | ,{accrual_activity_id:fh8EQzf0MPbjvyVd,groups:[],inputs:[],name:PM}] 4 | ,groups:[{accrual_group_id:"2TBJjDhGPZX3JHSY",activities:[],everyTally:null,housePercent:0,inputs:[],jackpot_id:63,last_accrual_id:null,last_accrual_set_id:null,name:"Bingo Ply",pricePerPack:null,startingValue:null,thresholds:[]} 5 | ,{accrual_group_id:fV$H7yYVXgjAqL$9,activities:[],everyTally:null,housePercent:0,inputs:[{PackageTypeId:162,accrual_input_group_id:ag4HSYYsT_0gjUtZ,activities:[],defaultAmount:0,fixedAmount:0,groups:[ref["accruals","groups",1]],isDaily:0,isIncrements:0,isWeekly:0,minimum:0,name:"Pickle Ball",scalePrice:0,sqlStatement:null,useDefault:0,useMinimum:0,useScalePrice:0}],jackpot_id:60,last_accrual_id:null,last_accrual_set_id:null,name:"Cash Ball",pricePerPack:null,startingValue:null,thresholds:[]} 6 | ,{accrual_group_id:IPtXaPZhg3gbYVF3,activities:[],everyTally:null,housePercent:0,inputs:[],jackpot_id:59,last_accrual_id:null,last_accrual_set_id:null,name:"Lucky 8 CD",pricePerPack:null,startingValue:null,thresholds:[]} 7 | ,{accrual_group_id:l2kgvZXuwpOLWfdH,activities:[],everyTally:null,housePercent:0,inputs:[{PackageTypeId:160,accrual_input_group_id:z2CiQ_XeXl3O9ebQ,activities:[],defaultAmount:0,fixedAmount:0 8 | ,groups:[ref["accruals","groups",3]],isDaily:0,isIncrements:0,isWeekly:0,minimum:0,name:"Fire Ball",scalePrice:0,sqlStatement:null,useDefault:0,useMinimum:0,useScalePrice:0}],jackpot_id:64,last_accrual_id:null,last_accrual_set_id:null,name:CBB,pricePerPack:null,startingValue:null,thresholds:[]} 9 | ,{accrual_group_id:n15h_5PJE9TbDN83,activities:[],everyTally:null,housePercent:0,inputs:[],jackpot_id:58,last_accrual_id:null,last_accrual_set_id:null,name:"Lucky 7 CD",pricePerPack:null,startingValue:null,thresholds:[]} 10 | ,{accrual_group_id:TUXyT$nRcDJzV4D6,activities:[],everyTally:null,housePercent:0,inputs:[],jackpot_id:62,last_accrual_id:null,last_accrual_set_id:null,name:"Bonus Ball",pricePerPack:null,startingValue:null,thresholds:[]} 11 | ,{accrual_group_id:Tv7m5nbS4$h528oC,activities:[],everyTally:null,housePercent:0,inputs:[],jackpot_id:65,last_accrual_id:null,last_accrual_set_id:null,name:"Bonus Ball JP",pricePerPack:null,startingValue:null,thresholds:[]} 12 | ,{accrual_group_id:Uj32Q7pabJELEKi9,activities:[],everyTally:null,housePercent:0,inputs:[],jackpot_id:66,last_accrual_id:null,last_accrual_set_id:null,name:"April Bonus Ball",pricePerPack:null,startingValue:null,thresholds:[]} 13 | ,{accrual_group_id:WcHz_$5Sze2mqKeM,activities:[],everyTally:null,housePercent:0,inputs:[],jackpot_id:61,last_accrual_id:null,last_accrual_set_id:null,name:"Cash Ball Frenzy",pricePerPack:null,startingValue:null,thresholds:[]}] 14 | ,inputs:[ref["accruals","groups",1,"inputs",0] 15 | ,{PackageTypeId:161,accrual_input_group_id:H81eUVnbPyWO8WZ4,activities:[],defaultAmount:0,fixedAmount:0,groups:[],isDaily:0,isIncrements:0,isWeekly:0,minimum:0,name:"4 Corners",scalePrice:0,sqlStatement:null,useDefault:0,useMinimum:0,useScalePrice:0} 16 | ,{PackageTypeId:164,accrual_input_group_id:I4UehKHUKh_9MP3W,activities:[],defaultAmount:0,fixedAmount:0,groups:[],isDaily:0,isIncrements:0,isWeekly:0,minimum:0,name:"Power Up+",scalePrice:0,sqlStatement:null,useDefault:0,useMinimum:0,useScalePrice:0} 17 | ,{PackageTypeId:159,accrual_input_group_id:PMGEywf7t0VQC19p,activities:[],defaultAmount:0,fixedAmount:0,groups:[],isDaily:0,isIncrements:0,isWeekly:0,minimum:0,name:"Bonus Ball",scalePrice:0,sqlStatement:null,useDefault:0,useMinimum:0,useScalePrice:0} 18 | ,{PackageTypeId:153,accrual_input_group_id:QE3JUY3Wyp$XI0d$,activities:[],defaultAmount:0,fixedAmount:0,groups:[],isDaily:0,isIncrements:0,isWeekly:0,minimum:0,name:JPTest,scalePrice:0,sqlStatement:null,useDefault:0,useMinimum:0,useScalePrice:0} 19 | ,{PackageTypeId:157,accrual_input_group_id:wzqxhnOHZM3c1w6J,activities:[],defaultAmount:0,fixedAmount:0,groups:[],isDaily:0,isIncrements:0,isWeekly:0,minimum:0,name:"Jackpot Test",scalePrice:0,sqlStatement:null,useDefault:0,useMinimum:0,useScalePrice:0} 20 | ,ref["accruals","groups",3,"inputs",0] 21 | ,{PackageTypeId:163,accrual_input_group_id:__2iVgZCeG4aGep4,activities:[],defaultAmount:0,fixedAmount:0,groups:[],isDaily:0,isIncrements:0,isWeekly:0,minimum:0,name:"Hawk Ball",scalePrice:0,sqlStatement:null,useDefault:0,useMinimum:0,useScalePrice:0}]} 22 | ,op:accruals} -------------------------------------------------------------------------------- /jsox.bnf: -------------------------------------------------------------------------------- 1 | 2 | jsox-stream 3 | jsox 4 | jsox jsox-stream 5 | 6 | jsox 7 | element 8 | 9 | value 10 | object 11 | array 12 | string 13 | numbertoken 14 | keywords 15 | typedobjectuse 16 | typedarray 17 | typedstring 18 | 19 | keywords 20 | "true" 21 | "false" 22 | "null" 23 | "NaN" 24 | "Infinity" 25 | "-" "Infinity" 26 | "undefined" 27 | 28 | delimiter 29 | "{" 30 | '[' 31 | ',' 32 | ':' 33 | ws 34 | 35 | closedelimiter 36 | '}' 37 | ']' 38 | ',' 39 | ws 40 | 41 | object 42 | '{' ws '}' 43 | '{' members '}' 44 | 45 | objectfields 46 | '{' identifiers '}' 47 | 48 | objectvalues 49 | '{' elements '}' 50 | 51 | members 52 | member 53 | member ',' members 54 | 55 | member 56 | ws string ws ':' element 57 | 58 | array 59 | '[' ws ']' 60 | '[' elements ']' 61 | 62 | typedarray 63 | identifier '[' ws ']' 64 | identifier '[' elements ']' 65 | 66 | typedstring 67 | identifier string 68 | identifier string 69 | 70 | typedobjectdef 71 | identifier objectfields 72 | 73 | typedobjectuse 74 | identifier objectvalues 75 | 76 | elements 77 | element 78 | element ',' elements 79 | 80 | element 81 | value 82 | value element 83 | 84 | identifiers 85 | identifier 86 | identifier ',' identifiers 87 | 88 | identifier 89 | string 90 | characters - nonidentifier - ws - keywords 91 | 92 | string 93 | '"' dqcharacters '"' 94 | '`' btcharacters '`' 95 | "'" sqcharacters "'" 96 | 97 | sqcharacters 98 | "" 99 | sqcharacter sqcharacters 100 | 101 | sqcharacter 102 | character - '\' - "'" 103 | '\' escape 104 | 105 | dqcharacters 106 | "" 107 | dqcharacter dqcharacters 108 | 109 | dqcharacter 110 | character - '"' - '\' 111 | '\' escape 112 | 113 | btcharacters 114 | "" 115 | btcharacter btcharacters 116 | 117 | btcharacter 118 | character - '\' - "`" 119 | '\' escape 120 | 121 | 122 | characters 123 | "" 124 | character characters 125 | 126 | character 127 | '\u{00000000}' . '\u{FFFFFFFF}' 128 | 129 | escape 130 | '"' 131 | "'" 132 | '`' 133 | '\' 134 | 'b' 135 | 'n' 136 | 'r' 137 | 't' 138 | 'u' hex hex hex hex 139 | 'u' '{ hex '}' 140 | '0' . '2' oct oct 141 | 'x' hex hex 142 | 143 | hexs 144 | hex 145 | hex hexs 146 | 147 | hex 148 | digit 149 | 'A' . 'F' 150 | 'a' . 'f' 151 | 152 | numbertoken 153 | number ws 154 | number ',' 155 | number '}' 156 | number ']' 157 | number 'n' 158 | date 'Z' 159 | 160 | number 161 | '+' number 162 | '-' number 163 | '.' digits frac exp 164 | digits frac exp 165 | int 166 | date 167 | onenine digits 'n' 168 | 169 | date 170 | digit date 171 | - 'e' '-' date 172 | ':' date 173 | '+' date 174 | 'T' date 175 | 'Z' 176 | 177 | int 178 | '0' 'x' hexs 179 | '0' 'X' hexs 180 | '0' 'o' octs 181 | '0' 'O' octs 182 | '0' 'b' bins 183 | '0' 'B' bins 184 | '0' octs 185 | onenine digits 186 | 187 | octs 188 | oct 189 | oct octs 190 | 191 | oct 192 | '0' . '7' 193 | 194 | bins 195 | bin 196 | bin bins 197 | 198 | bin 199 | '0' . '1' 200 | 201 | digits 202 | digit 203 | digit digits 204 | digit '_' digits 205 | digits '_' digit digits 206 | 207 | digit 208 | '0' 209 | onenine 210 | 211 | onenine 212 | '1' . '9' 213 | 214 | frac 215 | "" 216 | '.' 217 | 218 | exp 219 | "" 220 | 'E' sign digits 221 | 'e' sign digits 222 | 223 | sign 224 | "" 225 | '+' 226 | '-' 227 | 228 | ws 229 | "" 230 | '0009' ws 231 | '000a' ws 232 | '000d' ws 233 | '0020' ws 234 | '07EC' ws 235 | '07ED' ws 236 | 237 | breaking_ws 238 | '0009' ws 239 | '000a' ws 240 | '000d' ws 241 | '0020' ws 242 | '07EC' ws 243 | '07ED' ws 244 | 245 | line-comment 246 | '/' '/' characters '\n' 247 | 248 | block-comment 249 | '/' '*' characters '*' '/' 250 | 251 | nonidentifier 252 | '(' 253 | ')' 254 | '=' 255 | '+' 256 | '-' 257 | '*' 258 | '/' 259 | '\' 260 | '"' 261 | "'" 262 | "`" 263 | delimiter 264 | closedelimiter 265 | - unicode-non-identifier-characters 266 | 267 | unicode-non-identifier-characters 268 | -------------------------------------------------------------------------------- /tests/data/testReferenceRevive2.jsox: -------------------------------------------------------------------------------- 1 | 2 | { 3 | data: { 4 | data: { 5 | groups: [{ 6 | captain: { 7 | children: [], 8 | created: 2019-05-16T14:05:10.000-07:00, 9 | name: "Tom", 10 | parents: [{ 11 | children: [ 12 | ref["data","data","groups",0,"captain"], 13 | { 14 | children: [], 15 | created: 2019-05-16T14:05:10.000-07:00, 16 | name: "Alice", 17 | parents: [], 18 | siblings: [ 19 | ref["data","data","groups",0,"captain"], 20 | { 21 | children: [], 22 | created: 2019-05-16T14:05:10.000-07:00, 23 | name: "Bob", 24 | parents: [], 25 | siblings: [ 26 | ref["data","data","groups",0,"captain"], 27 | ref["data","data","groups",0,"captain","parents",0,"children",1,"siblings",1] 28 | ], 29 | spice: [], 30 | user_id: "YmZVBB7c1T2D9idyWmc75mWMBJNE$O6u_xOaGp4bwAk=" 31 | } 32 | ], 33 | spice: [], 34 | user_id: "6Q6Q8Ca1fCblmGhZYEzrC_Cbe5qxmyoGVjo1PrBImw0=" 35 | }, 36 | ref["data","data","groups",0,"captain","parents",0,"children",1,"siblings",1] 37 | ], 38 | created: 2019-05-16T14:05:10.000-07:00, 39 | name: "Jerrie", 40 | parents: [], 41 | siblings: [], 42 | spice: [ 43 | { 44 | children: [ 45 | ref["data","data","groups",0,"captain"], 46 | ref["data","data","groups",0,"captain","parents",0,"children",1], 47 | ref["data","data","groups",0,"captain","parents",0,"children",1,"siblings",1] 48 | ], 49 | created: 2019-05-16T14:05:10.000-07:00, 50 | name: "Harry", 51 | parents: [], 52 | siblings: [], 53 | spice: [], 54 | user_id: "nopYfH9gfEx$XE0nrT5YiRNBc5GeJDcEB031vPLERaI=" 55 | }, 56 | ref["data","data","groups",0,"captain","parents",0,"spice",0], 57 | ref["data","data","groups",0,"captain","parents",0] 58 | ], 59 | user_id: "L$zZTtjNH6DngoL8tWz7fn6QDKsEd3GpxcCAZIcKmOQ=" 60 | }, 61 | ref["data","data","groups",0,"captain","parents",0], 62 | ref["data","data","groups",0,"captain","parents",0,"spice",0] 63 | ], 64 | siblings: [ 65 | ref["data","data","groups",0,"captain","parents",0,"children",1], 66 | ref["data","data","groups",0,"captain","parents",0,"children",1,"siblings",1] 67 | ], 68 | spice: [], 69 | user_id: "jw56VioAX4E0VSalmDzRyv68gTjqUZp8PmESMZjJVsc=" 70 | }, 71 | members: { 72 | children: [], 73 | created: 2019-05-16T14:05:10.000-07:00, 74 | name: "Barb", 75 | parents: [ 76 | { 77 | children: [ 78 | ref["data","data","groups",0,"members"] 79 | ], 80 | created: 2019-05-16T14:05:10.000-07:00, 81 | name: "Monica", 82 | parents: [], 83 | siblings: [], 84 | spice: [], 85 | user_id: "ObPEfWqvehsAStM7HoMNiEdbGSCh2sbU6DmzlVNcevs=" 86 | }, 87 | ref["data","data","groups",0,"members","parents",0] 88 | ], 89 | siblings: [ 90 | { 91 | children: [], 92 | created: 2019-05-16T14:05:10.000-07:00, 93 | name: "Nick", 94 | parents: [], 95 | siblings: [], 96 | spice: [], 97 | user_id: "GAmo6jep_ZCxWG35m_QhcUN_UR1u5Q0za$Zbe2SqT68=" 98 | }, 99 | ref["data","data","groups",0,"members","siblings",0] 100 | ], 101 | spice: [], 102 | user_id: "YFLkultOF4hJgODgA56AbXMnYX$63VzuPcTS6vvH318=" 103 | }, 104 | name: "Group 1" 105 | }, 106 | ref["data","data","groups",0] 107 | ], 108 | tick: 2019-05-16T05:02:52.000-07:00, 109 | users: [ 110 | ref["data","data","groups",0,"captain"], 111 | ref["data","data","groups",0,"captain","parents",0,"children",1], 112 | ref["data","data","groups",0,"captain","parents",0,"children",1,"siblings",1], 113 | ref["data","data","groups",0,"captain","parents",0], 114 | ref["data","data","groups",0,"captain","parents",0,"spice",0], 115 | ref["data","data","groups",0,"members"], 116 | ref["data","data","groups",0,"members","siblings",0], 117 | ref["data","data","groups",0,"members","parents",0] 118 | ] 119 | }, 120 | nonce: null 121 | }, 122 | id: "7pXRYvN577MMLA1WS7laY42Hb_USTfRpz5JAVujsVK4=" 123 | } 124 | -------------------------------------------------------------------------------- /test/TestObjectKeys.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const JSON6 = require( ".." ); 3 | 4 | describe('Object keys', function () { 5 | describe('Erring', function () { 6 | it('Unencapsulated hyphenated key with space', function () { 7 | expect(function () { 8 | const result = JSON6.parse( "{ my- key:3}" ); 9 | //console.log( "result:", result ); 10 | }).to.throw(Error); 11 | }); 12 | 13 | it('Unencapsulated hyphenated key with spaces', function () { 14 | expect(function () { 15 | const result = JSON6.parse( "{ my - key:3}" ); 16 | //console.log( "result:", result ); 17 | }).to.throw(Error); 18 | }); 19 | 20 | /* JSOX handles this by reviving as a class of type 'my-key' 21 | it('Unencapsulated hyphenated key with nested object', function () { 22 | expect(function () { 23 | const result = JSON6.parse( "{ my-key { failure:true}:3}" ); 24 | console.log( "result:", result ); 25 | }).to.throw(Error); 26 | }); 27 | */ 28 | /* JSOX handles this as a valid string... 29 | it('Unencapsulated key with nested object', function () { 30 | expect(function () { 31 | const result = JSON6.parse( "{ { my-key:3 } }" ); 32 | console.log( "result:", result ); 33 | }).to.throw(Error); 34 | }); 35 | */ 36 | it('Unencapsulated key with nested array', function () { 37 | expect(function () { 38 | const result = JSON6.parse( "{ [ my-key:3 } }" ); 39 | //console.log( "result:", result ); 40 | }).to.throw(Error); 41 | }); 42 | 43 | it('Unencapsulated key with opening array bracket', function () { 44 | expect(function () { 45 | const result = JSON6.parse( "{ my-key[:3 } }" ); 46 | //console.log( "result:", result ); 47 | }).to.throw(Error); 48 | }); 49 | 50 | it('Unencapsulated key with closing array bracket', function () { 51 | expect(function () { 52 | const result = JSON6.parse( "{ my-key]:3 } }" ); 53 | //console.log( "result:", result ); 54 | }).to.throw(Error); 55 | }); 56 | 57 | it('Unencapsulated key with opening array bracket and space', function () { 58 | expect(function () { 59 | const result = JSON6.parse( "{ my-key [:3 } }" ); 60 | //console.log( "result:", result ); 61 | }).to.throw(Error); 62 | }); 63 | 64 | it('Unencapsulated key with closing array bracket and space', function () { 65 | expect(function () { 66 | const result = JSON6.parse( "{ my-key ]:3 } }" ); 67 | //console.log( "result:", result ); 68 | }).to.throw(Error); 69 | }); 70 | 71 | it('Key with quote not at beginning', function () { 72 | expect(function () { 73 | JSON6.parse( "{A': 3}" ); 74 | }).to.throw(Error, /Incomplete string at|Pending value could not complete/); 75 | }); 76 | }); 77 | 78 | describe('Functional', function () { 79 | it('Parses encapsulated key', function () { 80 | const result = JSON6.parse( "{ 'my - key':3}" ); 81 | 82 | //console.log( "result:", result ); 83 | expect(result).to.deep.equal({ 84 | 'my - key': 3 85 | }); 86 | }); 87 | 88 | it('Parses encapsulated key with carriage return', function () { 89 | const result = JSON6.parse( "{ '\\\rmy - key':3}" ); 90 | 91 | //console.log( "result:", result ); 92 | expect(result).to.deep.equal({ 93 | 'my - key': 3 94 | }); 95 | }); 96 | 97 | it('Parses key with special characters but no spaces', function () { 98 | const result = JSON6.parse( "{ my-key\\m&m+*|:3}" ); 99 | //console.log( "result:", result ); 100 | expect(result).to.deep.equal({ 101 | 'my-key\\m&m+*|' : 3 102 | }); 103 | }); 104 | 105 | it('Parses key with special characters and comment', function () { 106 | const result = JSON6.parse( "{ my-key //test \n :3}" ); 107 | //console.log( "result:", result ); 108 | /* 109 | { my-key //test 110 | :3} // valid 111 | */ 112 | expect(result).to.deep.equal({ 113 | 'my-key': 3 114 | }); 115 | }); 116 | 117 | it('Parses key with special characters and multi-line comment', function () { 118 | const result = JSON6.parse( "{ my-key /*test */ :3}" ); 119 | //console.log( "result:", result ); 120 | 121 | /* 122 | { my-key /*test * / :3} // valid 123 | */ 124 | expect(result).to.deep.equal({ 125 | 'my-key': 3 126 | }); 127 | }); 128 | 129 | it('Parses key with ZWNBS (ignoring it)', function () { 130 | const result = JSON6.parse( "{A\uFEFF: 3}" ); 131 | 132 | expect(result).to.deep.equal({ 133 | 'A': 3 134 | }); 135 | }); 136 | }); 137 | }); 138 | -------------------------------------------------------------------------------- /lib/jsox.min.d.ts: -------------------------------------------------------------------------------- 1 | export default JSOX; 2 | export namespace JSOX { 3 | export { JSOX }; 4 | export let version: string; 5 | export { DateNS }; 6 | /** 7 | * SACK jsox compatibility; hands maps to internal C++ code in other case. 8 | * @internal 9 | */ 10 | export function updateContext(): void; 11 | /** 12 | * Provide minimal escapes for a string to be encapsulated as a JSOX string in quotes. 13 | * 14 | * @param {string} string 15 | * @returns {string} 16 | */ 17 | export function escape(string: string): string; 18 | /** 19 | * reset JSOX parser entirely; clears all type mappings 20 | * 21 | * @returns {void} 22 | */ 23 | export function reset(): void; 24 | /** 25 | * Create a streaming parser. Add data with parser.write(data); values that 26 | * are found are dispatched to the callback. 27 | * 28 | * @param {(value:any) => void} [cb] 29 | * @param {(this: any, key: string, value: any) => any} [reviver] 30 | * @returns {JSOXParser} 31 | */ 32 | export function begin(cb?: (value: any) => void, reviver?: (this: any, key: string, value: any) => any): JSOXParser; 33 | /** 34 | * parse a string resulting with one value from it. 35 | * 36 | * @template T 37 | * @param {string} msg 38 | * @param {(this: any, key: string, value: any) => any} [reviver] 39 | * @returns {T} 40 | */ 41 | export function parse(msg: string, reviver?: (this: any, key: string, value: any) => any): T; 42 | /** 43 | * Define a class to be used for serialization; the class allows emitting the class fields ahead of time, and just provide values later. 44 | * @param {string} name 45 | * @param {object} obj 46 | */ 47 | export function defineClass(name: string, obj: object): void; 48 | /** 49 | * deprecated; define a class to be used for serialization 50 | * 51 | * @param {string} named 52 | * @param {class} ptype 53 | * @param {(any)=>any} f 54 | */ 55 | export function registerToJSOX(name: any, ptype: class, f: (any: any) => any): never; 56 | /** 57 | * define a class with special serialization rules. 58 | * 59 | * @param {string} named 60 | * @param {class} ptype 61 | * @param {(any)=>any} f 62 | */ 63 | export function toJSOX(name: any, ptype: class, f: (any: any) => any): void; 64 | /** 65 | * define a class to be used for deserialization 66 | * @param {string} prototypeName 67 | * @param {class} o 68 | * @param {(any)=>any} f 69 | */ 70 | export function fromJSOX(prototypeName: string, o: class, f: (any: any) => any): void; 71 | /** 72 | * deprecated; use fromJSOX instead 73 | */ 74 | export function registerFromJSOX(prototypeName: any, o: any): never; 75 | /** 76 | * Define serialization and deserialization methods for a class. 77 | * This is the same as registering separately with toJSOX and fromJSOX methods. 78 | * 79 | * @param {string} name - Name used to prefix objects of this type encoded in JSOX 80 | * @param {class} prototype - prototype to match when serializing, and to create instaces of when deserializing. 81 | * @param {(stringifier:JSOXStringifier)->{string}} to - `this` is the value to convert; function to call to encode JSOX from an object 82 | * @param {(field:string,val:any)->{any}} from - handle storing revived value in class 83 | */ 84 | export function addType(prototypeName: any, prototype: class, to: any, from: any): void; 85 | export function registerToFrom(prototypeName: any, prototype: any): never; 86 | /** 87 | * Create a stringifier to convert objects to JSOX text. Allows defining custom serialization for objects. 88 | * @returns {Stringifier} 89 | */ 90 | export function stringifier(): Stringifier; 91 | /** 92 | * @param {unknown} object 93 | * @param {(this: unknown, key: string, value: unknown)} [replacer] 94 | * @param {string | number} [space] 95 | * @returns {string} 96 | */ 97 | export function stringify(object: unknown, replacer?: (this: unknown, key: string, value: unknown) => any, space?: string | number): string; 98 | } 99 | /** 100 | * Extend Date type with a nanosecond field. 101 | * @constructor 102 | * @param {Date} original_date 103 | * @param {Number} nanoseconds in milli-seconds of Date ( 0 to 1_000_000 ) 104 | */ 105 | declare class DateNS extends Date { 106 | constructor(a: any, b: any); 107 | ns: any; 108 | } 109 | -------------------------------------------------------------------------------- /jsox2.ebnf: -------------------------------------------------------------------------------- 1 | Name = "JSON Grammar". 2 | Author = "d3x0r". 3 | Version = "1.0". 4 | 5 | WS = "(whitespace)" ( "\\x20" | "\\r" | "\\n" | "\\t" | "\\u07ec" | "\\u07ed" ) { "\\x20" | "\\r" | "\\n" | "\\t" | "\\u07ec" | "\\u07ed" } . 6 | 7 | LegalEscapes = "(Legal Escapes)" ( "b" | "n" | "r" | "f" | "t" | ("'" | '"' | "`") 8 | | ( "u" ( "{" {"0-9" | "A-F" | "a-f"} "}" | "4 hex digits" ) ) 9 | | ( "x" ("0-9" | "A-F" | "a-f") ("0-9" | "A-F" | "a-f") ) 10 | | ( "0-2" "0-7" "0-7" ) 11 | ). 12 | 13 | Val = "(Value)" ( 14 | ("(Comment)" ( ( "/" "/" { "character not \\n or \\r" } ("\\r"|"\\n") ) 15 | | ( "/" "*" { "character" } "*" "/" ) 16 | )| 17 | ( "(whitespace)" {( "\\x20" | "\\r" | "\\n" | "\\t" | "\\u07ec" | "\\u07ed" )} ) | 18 | ("(String)" ( '"'| "'"| "`") ( ( 'character not open-quote or \\ ' ) | ( '\\' '"' ) | ("\\" "\\" ) | ( "\\" "Legal Escapes" ) ) 19 | { ( 'character not open-quote or \\ ' ) | ( '\\' '"' ) | ("\\" "\\" ) | ( "\\" "Legal Escapes" ) } 20 | ) 21 | ( '"'| "'"| "`") )| 22 | ( "(ident)" ( "String" | ( ( "not \\u{FEFF}" | "non-digit" | "not { [ ( < > ) ] } , : \" ' ` ~ ! + - * / ." | "a-z" "A-Z" ) 23 | { "not \\u{FEFF}" | "non-digit" | "not { [ ( < > ) ] } , : \" ' ` ~ ! + - * / ." | "a-z" "A-Z" "0-9" } 24 | ) 25 | ) 26 | ) 27 | ( "(Object)" "{" ( (|"whitespace")ident(|"whitespace") ":" Value ) { "," ( (|"whitespace") ident (|"whitespace") ":" Value) } "}" ) | 28 | ( "(typed-object-def)" ident object ) | 29 | ( "(typed-object-use)" ident "{" ( Value ) { "," (Value) } "}" ) | 30 | ( "(Array)" "[" ( Value ) { "," Value } "]" ) | 31 | ( "(typed-array)" "ident" "Array" ) | 32 | ( "(typed-string)" "ident" String ) | 33 | ( |"-") ( "NaN" | "Infinity" | 34 | ( ( "-" | "+" ) { "-" | "+" } | ("0-9") ) "/*Number Parser Begin*/" 35 | ( ( "(BigInt)" (("0-9"){ "0-9"|"_" }) "n" ) | 36 | "(Number)"( "(int)" ( ( "if 0" {"_"} ( 37 | ( ( "x" | "X" ) ("0-9" | "A-F" | "a-f" |"_") {"0-9" | "A-F" | "a-f" |"_"} ) | 38 | ( ( "o" | "O" ) ("0-7"|"_") { "0-7"|"_" } ) | 39 | ( ( "b" | "B" ) ("0-1"|"_") { "0-1"|"_" } ) ) ) 40 | | ( ("0-9"|"_") {"0-9"|"_"} (| "(float)" (| "." { "0-9" |"_"} ) (| ( ( "e" | "E" ) (|"+"|"-"|"_") ("0-9"|"_") { "0-9"|"_" } ) ) ) ) 41 | ) 42 | 43 | ) 44 | | "(Date)" ( ( ( "0-9" |"-"){"0-9"|"-"} "T" ( "0-9" |":"){"0-9"|":"} (|"." ("0-9"){"0-9"} )) 45 | ( 46 | | "/*Timezone*/" ( ( |"+"|"-") "0-9" "0-9" ":" "0-9" "0-9" 47 | | "Z" ) ) ) 48 | 49 | )) | 50 | true | false | null | undefined ). 51 | 52 | PredefinedTypes = ( 53 | ( "(TypedArray)" ( "ab" | "u8" | "s8" | "u8" | "u16" | "s16" 54 | | "u32" 55 | | "s32" 56 | | "f32" 57 | | "f64" 58 | ) "[" "base64 ArrayBuffer bytes" "]" ) | 59 | ( "(reference)" "ref" "[" ( (|"whitespace")( "ident" | "int" ) (|"whitespace") { ("," (|"whitespace")( "ident" | "int" )(|"whitespace")) }) "]" ) 60 | 61 | ). 62 | 63 | NumberRule = ("(Number/Date/BigInt)" 64 | ( |"-") ( "NaN" | "Infinity" | 65 | ( ( "-" | "+" ) { "-" | "+" } | ("0-9") ) "/*Number Parser Begin*/" 66 | ( ( "(BigInt)" (("0-9"){ "0-9"|"_" }) "n" ) | 67 | "(Number)"( "(int)" ( ( "if 0" {"_"} ( 68 | ( ( "x" | "X" ) ("0-9" | "A-F" | "a-f" |"_") {"0-9" | "A-F" | "a-f" |"_"} ) | 69 | ( ( "o" | "O" ) ("0-7"|"_") { "0-7"|"_" } ) | 70 | ( ( "b" | "B" ) ("0-1"|"_") { "0-1"|"_" } ) ) ) 71 | | ( ("0-9"|"_") {"0-9"|"_"} (| "(float)" (| "." { "0-9" |"_"} ) (| ( ( "e" | "E" ) (|"+"|"-"|"_") ("0-9"|"_") { "0-9"|"_" } ) ) ) ) 72 | ) 73 | 74 | ) 75 | | "(Date)" ( ( ( "0-9" |"-"){"0-9"|"-"} "T" ( "0-9" |":"){"0-9"|":"} (|"." ("0-9"){"0-9"} )) 76 | ( 77 | | "/*Timezone*/" ( ( |"+"|"-") "0-9" "0-9" ":" "0-9" "0-9" 78 | | "Z" ) ) ) 79 | 80 | ))). 81 | --------------------------------------------------------------------------------