+1
-1
@@ -1,1 +0,1 @@ | ||
| {"name":"jju","version":"1.2.0","description":"a set of utilities to work with JSON / JSON5 documents","author":{"name":"Alex Kocharin","email":"alex@kocharin.ru"},"repository":{"type":"git","url":"git://github.com/rlidwka/jju"},"bugs":{"url":"https://github.com/rlidwka/jju/issues"},"homepage":"http://rlidwka.github.io/jju/","devDependencies":{"mocha":">=1.21.0","js-yaml":">=3.1.0","eslint":"~0.4.2"},"scripts":{"test":"mocha test/*.js","lint":"eslint -c ./.eslint.yaml ./lib"},"keywords":["json","json5","parser","serializer","data"],"publishConfig":{"registry":"https://registry.npmjs.org/"},"license":{"type":"WTFPL","url":"http://www.wtfpl.net/txt/copying/"}} | ||
| {"name":"jju","version":"1.2.1","description":"a set of utilities to work with JSON / JSON5 documents","author":{"name":"Alex Kocharin","email":"alex@kocharin.ru"},"repository":{"type":"git","url":"git://github.com/rlidwka/jju"},"bugs":{"url":"https://github.com/rlidwka/jju/issues"},"homepage":"http://rlidwka.github.io/jju/","devDependencies":{"mocha":">=1.21.0","js-yaml":">=3.1.0","eslint":"~0.4.2"},"scripts":{"test":"mocha test/*.js","lint":"eslint -c ./.eslint.yaml ./lib"},"keywords":["json","json5","parser","serializer","data"],"publishConfig":{"registry":"https://registry.npmjs.org/"},"license":{"type":"WTFPL","url":"http://www.wtfpl.net/txt/copying/"}} |
+1
-1
@@ -6,3 +6,3 @@ # use "yapm install ." if you're installing this from git repository | ||
| version: 1.2.0 | ||
| version: 1.2.1 | ||
| description: a set of utilities to work with JSON / JSON5 documents | ||
@@ -9,0 +9,0 @@ |
| root = true | ||
| [*] | ||
| charset = utf-8 | ||
| end_of_line = lf | ||
| trim_trailing_whitespace = true | ||
| insert_final_newline = true | ||
| [{.,}*.{js,json,json5,yml,yaml}] | ||
| indent_style = space | ||
| indent_size = 2 | ||
| [*.md] | ||
| indent_style = space | ||
| indent_size = 4 | ||
| trim_trailing_whitespace = false | ||
| [Makefile] | ||
| indent_style = tab |
| #!/usr/bin/env node | ||
| var Benchmark = require('benchmark') | ||
| var YAML = require('js-yaml') | ||
| var JJU = require('../') | ||
| var JSON5 = require('json5') | ||
| var suite = new Benchmark.Suite | ||
| var sample | ||
| sample = require('fs').readFileSync(__dirname + '/../package.yaml') | ||
| sample = YAML.safeLoad(sample) | ||
| sample = JSON.stringify(sample) | ||
| var functions = { | ||
| 'JSON': function(x) { JSON.parse(x) }, | ||
| 'JSON5': function(x) { JSON5.parse(x) }, | ||
| 'JJU': function(x) { JJU.parse(x) }, | ||
| 'JS-YAML': function(x) { YAML.safeLoad(x) }, | ||
| } | ||
| for (var name in functions) { | ||
| with ({ fn: functions[name] }) { | ||
| suite.add(name, { | ||
| onCycle: function onCycle(event) { | ||
| process.stdout.write('\r\033[2K - ' + event.target) | ||
| }, | ||
| fn: function () { | ||
| fn(sample) | ||
| }, | ||
| }) | ||
| } | ||
| } | ||
| console.log() | ||
| suite.on('cycle', function(event) { | ||
| console.log('\r\033[2K + ' + String(event.target)) | ||
| }) | ||
| .run() | ||
| process.on('exit', function() { console.log() }) |
| { | ||
| "name": "benchmarks", | ||
| "private": true, | ||
| "dependencies": { | ||
| "json5": "*", | ||
| "js-yaml": "*", | ||
| "benchmark": "*" | ||
| } | ||
| } |
-219
| JSON5 grammar expressed in EBNF form. | ||
| PS: I don't know what is appropriate syntax highlighter for this, so I'm using "modula2" because why not. I also inserted <ZWSP> after backslash to preserve syntax highlighting, this character has nothing to do with actual JSON5 syntax and should be ignored. | ||
| ```modula2 | ||
| json5_text = expression_with_whitespace | ||
| expression_with_whitespace = [white_space] , expression , [white_space] | ||
| expression = literal | ||
| | array_literal | ||
| | object_literal | ||
| literal = null_literal | ||
| | boolean_literal | ||
| | signed_numeric_literal | ||
| | string_literal | ||
| null_literal = 'null' | ||
| boolean_literal = 'true' | ||
| | 'false' | ||
| (* Source Characters *) | ||
| source_character = . | ||
| (* any Unicode code unit *) | ||
| line_terminator = <LF> | ||
| | <CR> | ||
| | <LS> | ||
| | <PS> | ||
| line_terminator_sequence = <LF> | ||
| | <CR> | ||
| | <LS> | ||
| | <PS> | ||
| | <CR> , <LF> | ||
| white_space = white_space_element | ||
| | white_space , white_space_element | ||
| white_space_element = white_space_character | ||
| | comment | ||
| white_space_character = <TAB> | ||
| | <VT> | ||
| | <FF> | ||
| | <SP> | ||
| | <NBSP> | ||
| | <BOM> | ||
| | <USP> | ||
| comment = multi_line_comment | ||
| | single_line_comment | ||
| multi_line_comment = '/*' , [multi_line_comment_chars] , '*/' | ||
| multi_line_comment_chars = (source_character - '*') , [multi_line_comment_chars] | ||
| | '*' , [post_asterisk_comment_chars] | ||
| post_asterisk_comment_chars = (source_character - ('*' | '/')) , [multi_line_comment_chars] | ||
| | '*' , [post_asterisk_comment_chars] | ||
| single_line_comment = '//' , [single_line_comment_chars] | ||
| single_line_comment_chars = single_line_comment_char , single_line_comment_chars | ||
| single_line_comment_char = source_character - line_terminator | ||
| (* Character classes *) | ||
| decimal_digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | ||
| non_zero_digit = decimal_digit - '0' | ||
| hex_digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'a' | ||
| | 'b' | 'c' | 'd' | 'e' | 'f' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | ||
| ascii_letter = ascii_letter_lowercase | ||
| | ascii_letter_uppercase | ||
| ascii_letter_lowercase = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | ||
| | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | ||
| | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' | ||
| ascii_letter_uppercase = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | ||
| | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | ||
| | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' | ||
| (* Numeric Literals *) | ||
| signed_numeric_literal = '-' , numeric_literal | ||
| | '+' , numeric_literal | ||
| | numeric_literal | ||
| numeric_literal = decimal_literal | ||
| | hex_integer_literal | ||
| | non_finite_literal | ||
| non_finite_literal = 'Infinity' | ||
| | 'NaN' | ||
| decimal_literal = decimal_integer_literal , '.' , [decimal_digits] , [exponent_part] | ||
| | '.' , decimal_digits , [exponent_part] | ||
| | decimal_integer_literal , [exponent_part] | ||
| decimal_integer_literal = '0' | ||
| | non_zero_digit , [decimal_digits] | ||
| decimal_digits = decimal_digit | ||
| | decimal_digits , decimal_digit | ||
| exponent_part = exponent_indicator , signed_integer | ||
| exponent_indicator = 'e' | 'E' | ||
| signed_integer = decimal_digits | ||
| | '+' , decimal_digits | ||
| | '-' , decimal_digits | ||
| hex_integer_literal = '0x' , hex_digit | ||
| | '0X' , hex_digit | ||
| | hex_integer_literal , hex_digit | ||
| (* String Literals *) | ||
| string_literal = '"' , [double_string_characters] , '"' | ||
| | "'" , [single_string_characters] , "'" | ||
| double_string_characters = double_string_character , [double_string_characters] | ||
| single_string_characters = single_string_character , [single_string_characters] | ||
| double_string_character = source_character - ('"' | '\' | line_terminator) | ||
| | '\' , escape_sequence | ||
| | line_continuation | ||
| single_string_character = source_character - ("'" | '\' | line_terminator) | ||
| | '\' , escape_sequence | ||
| | line_continuation | ||
| line_continuation = '\' , line_terminator_sequence | ||
| escape_sequence = character_escape_sequence | ||
| | '0' | ||
| | hex_escape_sequence | ||
| | unicode_escape_sequence | ||
| character_escape_sequence = single_escape_character | ||
| | non_escape_character | ||
| single_escape_character = '"' | "'" | '\' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | ||
| non_escape_character = source_character - (escape_character | line_terminator) | ||
| escape_character = single_escape_character | ||
| | decimal_digit | ||
| | 'x' | ||
| | 'u' | ||
| hex_escape_sequence = 'x' , hex_digit , hex_digit | ||
| unicode_escape_sequence = 'u' , hex_digit , hex_digit , hex_digit , hex_digit | ||
| (* Array Literals *) | ||
| array_literal = '[' , [white_space] , ']' | ||
| | '[' , [white_space] , element_list , ']' | ||
| | '[' , [white_space] , element_list , ',' , [white_space] , ']' | ||
| element_list = expression , [white_space] | ||
| | element_list , ',' , [white_space] , expression , [white_space] | ||
| (* Object Literals *) | ||
| object_literal = '{' , [white_space] , '}' | ||
| | '{' , [white_space] , property_name_and_value_list , '}' | ||
| | '{' , [white_space] , property_name_and_value_list , ',' , '}' | ||
| property_name_and_value_list = property_assignment , [white_space] | ||
| | property_name_and_value_list , [white_space] , ',' , [white_space] , property_assignment , [white_space] | ||
| property_assignment = property_name , [white_space] , ':' , [white_space] , expression | ||
| property_name = identifier_name | ||
| | string_literal | ||
| | numeric_literal | ||
| identifier_name = identifier_start | ||
| | identifier_name , identifier_part | ||
| identifier_start = unicode_letter | ||
| | '$' | ||
| | '_' | ||
| | '\' , unicode_escape_sequence | ||
| identifier_part = identifier_start | ||
| | unicode_combining_mark | ||
| | unicode_digit | ||
| | unicode_connector_punctuation | ||
| | <ZWNJ> | ||
| | <ZWJ> | ||
| unicode_letter = ascii_letter | ||
| (* + any character in the Unicode categories "Uppercase letter (Lu)", "Lowercase letter (Ll)", "Titlecase letter (Lt)", "Modifier letter (Lm)", "Other letter (Lo)", or "Letter number (Nl)" *) | ||
| unicode_combining_mark = | ||
| (* + any character in the Unicode categories "Non-spacing mark (Mn)" or "Combining spacing mark (Mc)" *) | ||
| unicode_digit = decimal_digit | ||
| (* + any character in the Unicode category "Decimal number (Nd)" *) | ||
| unicode_connector_punctuation = | ||
| (* + any character in the Unicode category "Connector punctuation (Pc)" *) | ||
| ``` |
| ## JSON5 syntax | ||
| We support slighly modified version of JSON5, see https://groups.google.com/forum/#!topic/json5/3DjClVYI6Wg | ||
| I started from ES5 specification and added a set of additional restrictions on top of ES5 spec. So I'd expect my implementation to be much closer to javascript. It's no longer an extension of json, but a reduction of ecmascript, which was my original intent. | ||
| This JSON5 version is a subset of ES5 language, specification is here: | ||
| http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf | ||
| This is a language that defines data structures only, so following notes/restrictions are applied: | ||
| - Literals (NullLiteral, BooleanLiteral, NumericLiteral, StringLiteral) are allowed. | ||
| - Compatibility syntax is not supported, which means octal literals are forbidden. | ||
| - ArrayLiterals and allowed, but instead of AssignmentExpressions you can only use other allowed Literals, ArrayLiterals and ObjectLiterals. Elisions are currently not supported. | ||
| - ObjectLiterals and allowed, but instead of AssignmentExpressions you can only use other allowed Literals, ArrayLiterals and ObjectLiterals. Setters and getters are forbidden. | ||
| - All other primary expressions ("this", Identifier, Expression) are forbidden. | ||
| - Two unary expressions ('-' and '+') allowed before NumericLiterals. | ||
| - Any data that has a number type can be represented, including +0, -0, +Infinity, -Infinity and NaN. | ||
| - "undefined" is forbidden, use null instead if applicable. | ||
| - Comments and whitespace are defined according to spec. | ||
| Main authority here is ES5 spec, so strict backward JSON compatibility is not guaranteed. | ||
| If you're unsure whether a behaviour of this library is a bug or not, you can run this test: | ||
| ```javascript | ||
| JSON5.parse(String(something)) | ||
| ``` | ||
| Should always be equal to: | ||
| ```javascript | ||
| eval('(function(){return ('+String(something)+'\n)\n})()') | ||
| ``` | ||
| If `something` meets all rules above. Parens and newlines in the example above are carefully placed so comments and another newlines will work properly, so don't look so impressed about that. | ||
| ## Weirdness of JSON5 | ||
| These are the parts that I don't particulary like, but see no good way to fix: | ||
| - no elisions, `[,,,] -> [null,null,null]` | ||
| - `[Object], [Circular]` aren't parsed | ||
| - no way of nicely representing multiline strings | ||
| - unicode property names are way to hard to implement | ||
| - Date and other custom objects | ||
| - incompatible with YAML (at least comments) |
| # vi:set ts=2 sts=2 sw=2 et: | ||
| # | ||
| # Copyright (c) JD 2456730 Alex Kocharin <alex@kocharin.ru> | ||
| # | ||
| # Permission to use, copy, modify, and/or distribute this software for any | ||
| # purpose with or without fee is hereby granted, provided that the above | ||
| # copyright notice and this permission notice appear in all copies. | ||
| # | ||
| # The original file is available here: | ||
| # https://github.com/rlidwka/jju/tree/master/test/portable-json5-tests.yaml | ||
| # | ||
| # ---------------------------------------------------------------------------- | ||
| # | ||
| # Portable JSON5 test suite. | ||
| # | ||
| # This file contains an actual YAML data and it may include fancy syntax. | ||
| # If your platform does not support YAML, you might wish to pre-process it | ||
| # using a generic YAML parser. | ||
| # | ||
| %YAML 1.2 | ||
| --- | ||
| # | ||
| # "input" is an arbitrary JSON5 you have to parse | ||
| # "output" is a normalized JSON you have to compare your result with, | ||
| # or !error (null) if your input should result in parser error | ||
| # | ||
| # Types of tests: | ||
| # | ||
| # - basic - Tests that every JSON5 parser should pass. | ||
| # | ||
| # - advanced - Tests that bring close compatibility with javascript. Not | ||
| # strictly required, but nice to have for completeness. | ||
| # | ||
| # - extra - Extra test cases you can follow at your discretion. | ||
| # | ||
| # Questionable features like elisions go to extra. All valid javascript, but | ||
| # invalid json5 also goes to extra. Feel free to ignore this section if you | ||
| # want to. Thus, eval(input) is a complete json5 parser, that should pass all | ||
| # basic and advanced tests. | ||
| # | ||
| # Basic types in minimal form | ||
| # --------------------------- | ||
| type-no-data: | ||
| type: extra | ||
| output: !error | ||
| input: '' | ||
| type-null: | ||
| type: basic | ||
| output: null | ||
| input: > | ||
| null | ||
| # undefined is not supported, | ||
| # null should be used instead | ||
| type-no-undefined: | ||
| type: extra | ||
| output: !error | ||
| input: > | ||
| undefined | ||
| type-no-raw: | ||
| type: extra | ||
| output: !error | ||
| input: > | ||
| foobar | ||
| type-bool-true: | ||
| type: basic | ||
| output: true | ||
| input: > | ||
| true | ||
| type-bool-false: | ||
| type: basic | ||
| output: false | ||
| input: > | ||
| false | ||
| type-number: | ||
| type: basic | ||
| output: 0 | ||
| input: > | ||
| 0 | ||
| type-string: | ||
| type: basic | ||
| output: "" | ||
| input: > | ||
| "" | ||
| type-object: | ||
| type: basic | ||
| output: {} | ||
| input: > | ||
| {} | ||
| type-array: | ||
| type: basic | ||
| output: [] | ||
| input: > | ||
| [] | ||
| # Numbers: special | ||
| # ---------------- | ||
| # note: it's hard to test this | ||
| # just add `1/x < 0` check in your code somewhere | ||
| num-negative-zero: | ||
| type: extra | ||
| output: -0.0 | ||
| input: > | ||
| -0 | ||
| num-nan: | ||
| type: basic | ||
| output: .nan | ||
| input: > | ||
| NaN | ||
| num-signed-nan: | ||
| type: basic | ||
| output: .nan | ||
| input: > | ||
| +NaN | ||
| num-positive-inf: | ||
| type: basic | ||
| output: +.inf | ||
| input: > | ||
| Infinity | ||
| num-negative-inf: | ||
| type: basic | ||
| output: -.inf | ||
| input: > | ||
| -Infinity | ||
| num-inf-exact-case: | ||
| type: extra | ||
| output: !error | ||
| input: > | ||
| INFINITY | ||
| # Numbers: hexadecimal | ||
| # -------------------- | ||
| num-hex-zero: | ||
| type: basic | ||
| output: 0 | ||
| input: > | ||
| 0x0 | ||
| num-cut-hex: | ||
| type: basic | ||
| output: !error | ||
| input: > | ||
| 0x | ||
| num-all-hex: | ||
| type: basic | ||
| output: 12841684683518 | ||
| input: > | ||
| 0xBADF00DCAFE | ||
| num-mixed-case: | ||
| type: basic | ||
| output: 3735928559 | ||
| input: > | ||
| 0xDeAdBEef | ||
| num-signed-hex: | ||
| type: advanced | ||
| output: 31 | ||
| input: > | ||
| +0x1F | ||
| num-negative-hex: | ||
| type: advanced | ||
| output: -31 | ||
| input: > | ||
| -0x1f | ||
| num-bad-hex: | ||
| type: advanced | ||
| output: !error | ||
| input: > | ||
| 0xBADxF00D | ||
| num-no-hex-float: | ||
| type: advanced | ||
| output: !error | ||
| input: > | ||
| 0x12.345 | ||
| # this is not actually an exponent :) | ||
| num-hex-exponent: | ||
| type: advanced | ||
| output: 4836 | ||
| input: > | ||
| 0x0012e4 | ||
| # Numbers: octal | ||
| # -------------- | ||
| # Octals are primarily used in config files | ||
| # to set up a file mask (like 0777) | ||
| # | ||
| # Note: they will have 0o12345 syntax instead | ||
| # of 012345 in the ES6, so we'll need to switch | ||
| # as well in the future | ||
| num-octal: | ||
| type: extra | ||
| output: 342391 | ||
| input: > | ||
| 01234567 | ||
| num-octal-zeroes: | ||
| type: extra | ||
| output: -24000 | ||
| input: > | ||
| -000000056700 | ||
| num-bad-octal: | ||
| type: extra | ||
| output: !error | ||
| input: > | ||
| 012345678 | ||
| num-no-octal-float: | ||
| type: extra | ||
| output: !error | ||
| input: > | ||
| 012.345 | ||
| num-no-octal-exp: | ||
| type: extra | ||
| output: !error | ||
| input: > | ||
| 0123e4 | ||
| # Numbers: floating point | ||
| # ----------------------- | ||
| num-float: | ||
| type: basic | ||
| output: 123.456 | ||
| input: > | ||
| 123.456 | ||
| num-signed-foat: | ||
| type: basic | ||
| output: -0.00098765 | ||
| input: > | ||
| -0.00098765 | ||
| num-omit-trailing-mantissa: | ||
| type: basic | ||
| output: 1234000 | ||
| input: > | ||
| 1234.e3 | ||
| num-omit-leading-mantissa: | ||
| type: advanced | ||
| output: -123.4 | ||
| input: > | ||
| -.1234e3 | ||
| num-bad-float: | ||
| type: advanced | ||
| output: !error | ||
| input: > | ||
| 0.12.345 | ||
| num-bad-sum: | ||
| type: extra | ||
| output: !error | ||
| input: > | ||
| 0.12+345 | ||
| num-uc-exp: | ||
| type: advanced | ||
| output: -1230000 | ||
| input: > | ||
| -123E+4 | ||
| num-float-exp: | ||
| type: basic | ||
| output: 123000 | ||
| input: > | ||
| 0.0123e7 | ||
| num-bad-exp: | ||
| type: extra | ||
| output: !error | ||
| input: > | ||
| 123e7.3 | ||
| num-bad-char: | ||
| type: extra | ||
| output: !error | ||
| input: > | ||
| 123a456 | ||
| num-no-exp: | ||
| type: advanced | ||
| output: !error | ||
| input: > | ||
| 123e | ||
| num-zero-exp: | ||
| type: advanced | ||
| output: -0.0 | ||
| input: > | ||
| -.00e-0 | ||
| num-dec-base-signed-exp: | ||
| type: advanced | ||
| output: 0.00000123 | ||
| input: > | ||
| 1230000E-012 | ||
| # String: quotes | ||
| # -------------- | ||
| string-double-quotes: | ||
| type: basic | ||
| output: foobar | ||
| input: > | ||
| "foobar" | ||
| string-single-quotes: | ||
| type: basic | ||
| output: foobar | ||
| input: > | ||
| 'foobar' | ||
| string-open: | ||
| type: basic | ||
| output: !error | ||
| input: > | ||
| "\\\\\\\\\\\\\" | ||
| string-not-open: | ||
| type: basic | ||
| output: "\\\\\\\\\\\\\\" | ||
| input: > | ||
| "\\\\\\\\\\\\\\" | ||
| string-continuation: | ||
| type: advanced | ||
| output: " foo bar " | ||
| input: > | ||
| " foo \ | ||
| bar \ | ||
| " | ||
| string-win-continuation: | ||
| type: advanced | ||
| output: "foobar" | ||
| input: "'foo\\\r\nbar'" | ||
| string-win-reverse-continuation: | ||
| type: advanced | ||
| output: !error | ||
| input: "'foo\\\n\rbar'" | ||
| string-unicode-continuation: | ||
| type: advanced | ||
| output: "foobarbaz" | ||
| input: "'foo\\\u2028bar\\\u2029baz'" | ||
| string-multi-bad-continuation: | ||
| type: advanced | ||
| output: !error | ||
| input: > | ||
| foo\ | ||
| bar | ||
| string-bad-ending: | ||
| type: basic | ||
| output: !error | ||
| input: "'foo\rbar'" | ||
| string-bad-ending-2028: | ||
| type: advanced | ||
| output: !error | ||
| input: "'foo\u2028bar'" | ||
| string-bad-ending-2029: | ||
| type: advanced | ||
| output: !error | ||
| input: "'foo\u2029bar'" | ||
| string-literal-unicode: | ||
| type: advanced | ||
| output: "foo\uFEFF\u2030bar\u1234" | ||
| input: "'foo\uFEFF\u2030bar\u1234'" | ||
| string-control-char: | ||
| type: advanced | ||
| output: "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f" | ||
| input: "'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f'" | ||
| # String: escape sequences | ||
| # ------------------------ | ||
| string-octal-escape: | ||
| type: extra | ||
| output: "\x1b[1;32mhi\x1b[m??" | ||
| input: > | ||
| '\033[1;32mhi\033[m\077\077' | ||
| string-octal-two-digits: | ||
| type: extra | ||
| output: "\n\x1c\x2e\x07890\x01" | ||
| input: > | ||
| '\12\34\56\78\90\1' | ||
| string-octal-three-digits: | ||
| type: extra | ||
| output: "\n34.78\xff 0" | ||
| input: > | ||
| '\01234\5678\377\400' | ||
| string-hex-escape: | ||
| type: extra | ||
| output: "\x01\x23\xab\xcd\xef" | ||
| input: > | ||
| "\x01\x23\xab\xCd\xEF" | ||
| # \0 is *not* an octal escape sequence, | ||
| # and is allowed even in strict mode | ||
| string-zero-point: | ||
| type: basic | ||
| output: "\0" | ||
| input: > | ||
| '\0' | ||
| string-escape-double-quotes: | ||
| type: basic | ||
| output: "\"''" | ||
| input: > | ||
| "\"'\'" | ||
| string-escape-single-quotes: | ||
| type: basic | ||
| output: " '\"\" " | ||
| input: > | ||
| ' \'"\" ' | ||
| string-escape-json-chars: | ||
| type: basic | ||
| output: "\\\/\b\f\n\r\t" | ||
| input: > | ||
| "\\\/\b\f\n\r\t" | ||
| # this character was left out of | ||
| # json spec for whatever reason | ||
| string-escape-slash-v: | ||
| type: basic | ||
| output: "\v" | ||
| input: > | ||
| "\v" | ||
| string-unicode-escape: | ||
| type: basic | ||
| output: "\u0000\uffffx\ufeff\u1234\u9f6a\u2028\uabcd" | ||
| input: > | ||
| "\u0000\uFFFFx\uFeFf\u1234\u9F6a\u2028\uabcd" | ||
| string-arbitrary-escape: | ||
| type: advanced | ||
| output: "X12Uqwe\r\tyiopasd\fghjklzc\u000b\b\nm9 " | ||
| input: > | ||
| '\X12\U\q\w\e\r\t\y\i\o\p\a\s\d\f\g\h\j\k\l\z\c\v\b\n\m\9\ ' | ||
| string-bad-unicode: | ||
| type: advanced | ||
| output: !error | ||
| input: > | ||
| '\uEFGH' | ||
| string-incomplete-unicode: | ||
| type: advanced | ||
| output: !error | ||
| input: > | ||
| '\u$' | ||
| string-bad-hex: | ||
| type: advanced | ||
| output: !error | ||
| input: > | ||
| '\xFG' | ||
| string-incomplete-hex: | ||
| type: advanced | ||
| output: !error | ||
| input: > | ||
| '\x$' | ||
| # Object literals | ||
| # --------------- | ||
| object-nested: | ||
| type: basic | ||
| output: {q:{'w':{"e":[1]}}} | ||
| input: | | ||
| {q:{'w':{"e":[1]}}} | ||
| object-trailing-comma: | ||
| type: basic | ||
| output: {foo: 'bar'} | ||
| input: | | ||
| {foo: 'bar',} | ||
| object-leading-comma-style: | ||
| type: basic | ||
| output: {q: 1,w: 2,e: 3} | ||
| input: | | ||
| { q: 1 | ||
| , w: 2 | ||
| , e: 3 | ||
| } | ||
| object-incomplete: | ||
| type: basic | ||
| output: !error | ||
| input: | | ||
| {q:1,w:2,{} | ||
| object-isnt-array: | ||
| type: basic | ||
| output: !error | ||
| input: | | ||
| {1,2} | ||
| object-no-single-comma: | ||
| type: basic | ||
| output: !error | ||
| input: | | ||
| {,} | ||
| object-no-elisions: | ||
| type: basic | ||
| output: !error | ||
| input: | | ||
| {q:1,,w:2} | ||
| # Objects: keys | ||
| # ------------- | ||
| object-singlequoted: | ||
| type: basic | ||
| output: {q: 1,w: 2,e: 3} | ||
| input: | | ||
| {'q':1,'w':2,'e':3} | ||
| object-doublequoted: | ||
| type: basic | ||
| output: {q: 1,w: 2,e: 3} | ||
| input: | | ||
| {"q":1,"w":2,"e":3} | ||
| object-unquoted: | ||
| type: basic | ||
| output: {$FOO_bar123: 'baz'} | ||
| input: > | ||
| {$FOO_bar123: 'baz'} | ||
| object-no-first-digit: | ||
| type: advanced | ||
| output: !error | ||
| input: > | ||
| {123foo: bar} | ||
| object-unquoted-unicode: | ||
| type: advanced | ||
| output: {"\u1f04\u03bb\u03c6\u03b1": baz} | ||
| input: "{\u1f04\u03bb\u03c6\u03b1:'baz'}" | ||
| object-unicode-escape-key: | ||
| type: advanced | ||
| output: {foo: 'bar', "\u1f04\u03bb\u03c6\u03b1": baz, "qwe\u1f04rty": quux} | ||
| input: | | ||
| {foo:'bar', \u1f04\u03bb\u03c6\u03b1:'baz', qwe\u1f04rty: "quux"} | ||
| object-no-raw-literal: | ||
| type: extra | ||
| output: !error | ||
| input: | | ||
| {foo: bar} | ||
| object-bad-literal: | ||
| type: advanced | ||
| output: !error | ||
| input: | | ||
| {foo-bar: 123} | ||
| object-no-space-in-key: | ||
| type: advanced | ||
| output: !error | ||
| input: | | ||
| {foo bar: 123} | ||
| object-no-comment-in-key: | ||
| type: advanced | ||
| output: !error | ||
| input: | | ||
| {foo/*bar*/baz: 123} | ||
| object-float-keys: | ||
| type: advanced | ||
| output: {'1': 'one', '3.1415': 'pi'} | ||
| input: | | ||
| {1:'one', 3.1415:'pi'} | ||
| object-no-negative: | ||
| type: advanced | ||
| output: !error | ||
| input: | | ||
| {-5: 123} | ||
| object-exponent-keys: | ||
| type: advanced | ||
| output: {'1': 'exp', '1000': 'pos', '0.001': 'neg'} | ||
| input: | | ||
| {1e0: 'exp', 1e+3: 'pos', 1e-3: 'neg'} | ||
| object-octal-keys: | ||
| type: extra | ||
| output: {'668': 1} | ||
| input: | | ||
| {01234: 1} | ||
| object-hex-keys: | ||
| type: advanced | ||
| output: {'51966': 1} | ||
| input: | | ||
| {0xCAFE: 1} | ||
| object-null-keys: | ||
| type: basic | ||
| output: {'null': null} | ||
| input: | | ||
| {null: null} | ||
| object-no-array-keys: | ||
| type: extra | ||
| output: !error | ||
| input: | | ||
| {[]: 123} | ||
| object-no-empty-keys: | ||
| type: basic | ||
| output: !error | ||
| input: | | ||
| {: 123} | ||
| object-empty-string-key: | ||
| type: basic | ||
| output: {s: {'': 1}, m: {'': 2}} | ||
| input: | | ||
| {s: {'': 1}, m: {"": 2}} | ||
| object-bad-unicode-space: | ||
| type: advanced | ||
| output: !error | ||
| input: | | ||
| { \u0020foobar: 123 } | ||
| object-bad-unicode-dash: | ||
| type: advanced | ||
| output: !error | ||
| input: | | ||
| { foo\u002dbar: 123} | ||
| object-incomplete-unicode-sequence: | ||
| type: advanced | ||
| output: !error | ||
| input: | | ||
| { foo\u12f: 123 } | ||
| object-double-escape: | ||
| type: advanced | ||
| output: !error | ||
| input: | | ||
| { foo\\u1234bar: 123 } | ||
| object-we-arent-es3: | ||
| type: basic | ||
| output: {new: 1, delete: 2, throw: 3} | ||
| input: | | ||
| {new: 1, delete: 2, throw: 3} | ||
| object-last-digits: | ||
| type: basic | ||
| output: {$123e2: 1, abc123: 2} | ||
| input: | | ||
| {$123e2: 1, abc123: 2} | ||
| object-unicode-in-string: | ||
| type: advanced | ||
| output: {"\uff13qwe": 123} | ||
| input: | | ||
| {"\uff13qwe": 123} | ||
| object-unicode-esc-in-string: | ||
| type: advanced | ||
| output: {"\\uff13qwe": 123} | ||
| input: | | ||
| {"\\uff13qwe": 123} | ||
| object-unicode-digits-first-esc: | ||
| type: advanced | ||
| output: !error | ||
| input: | | ||
| {\uff13qwe: 123} | ||
| object-unicode-digits-first-lit: | ||
| type: advanced | ||
| output: !error | ||
| input: "{\uff13qwe: 123}" | ||
| object-unicode-weirdness-esc: | ||
| type: advanced | ||
| output: {"digit\uff13": 1, "comb\u094F": 2, "punct\u2040": 3, "zwnj\u200C": 4} | ||
| input: | | ||
| {digit\uff13: 1, comb\u094F: 2, punct\u2040: 3, zwnj\u200C: 4} | ||
| object-unicode-weirdness-lit: | ||
| type: advanced | ||
| output: {"digit\uff13": 1, "comb\u094F": 2, "punct\u2040": 3, "zwnj\u200C": 4} | ||
| input: "{digit\uff13: 1, comb\u094F: 2, punct\u2040: 3, zwnj\u200C: 4}" | ||
| # Array literals | ||
| # -------------- | ||
| array-all-types: | ||
| type: basic | ||
| output: [1.2,"3,4",{},[],null,+.inf] | ||
| input: | | ||
| [1.2,"3,4",{},[],null,Infinity] | ||
| array-trailing-comma: | ||
| type: basic | ||
| output: [1,2,3,4] | ||
| input: | | ||
| [1,2,3,4,] | ||
| array-leading-comma-style: | ||
| type: basic | ||
| output: [quux,foo,bar,baz] | ||
| input: | | ||
| [ 'quux' | ||
| , 'foo' | ||
| , 'bar' | ||
| , 'baz' | ||
| ] | ||
| array-incomplete: | ||
| type: basic | ||
| output: !error | ||
| input: | | ||
| [1,2,3,[] | ||
| array-nested: | ||
| type: basic | ||
| output: [[[[[[]]]]],[[],[]]] | ||
| input: | | ||
| [[[[[[/*[]*/]]]]],[[],[]]] | ||
| array-isnt-object: | ||
| type: extra | ||
| output: !error | ||
| input: | | ||
| [1:2] | ||
| array-no-single-comma: | ||
| type: extra | ||
| output: !error | ||
| input: | | ||
| [,] | ||
| array-no-elisions: | ||
| type: extra | ||
| output: !error | ||
| input: | | ||
| [1,,2,3] | ||
| # Comments | ||
| # -------- | ||
| comment-single: | ||
| type: basic | ||
| output: foobar | ||
| input: | | ||
| // blahblah | ||
| "foobar" | ||
| // another one | ||
| comment-multi: | ||
| type: basic | ||
| output: foobar | ||
| input: | | ||
| /* | ||
| * 123 | ||
| */ | ||
| "foobar" | ||
| /**/ | ||
| comment-single-newlines: | ||
| type: advanced | ||
| output: [ 123, 456, 789 ] | ||
| input: "[// foo\r123,// bar\u2028456,// baz\u2029789]" | ||
| comment-inside: | ||
| type: advanced | ||
| output: [123, '// foo', '/* bar'] | ||
| input: > | ||
| [ | ||
| /* | ||
| " // */ 123, // ", | ||
| "// foo", | ||
| '/* bar', | ||
| ] | ||
| comment-in-token: | ||
| type: advanced | ||
| output: !error | ||
| input: | ||
| 123/*comment*/456 | ||
| comment-java-style: | ||
| type: basic | ||
| output: 123 | ||
| input: | ||
| /*****************/ | ||
| 123 | ||
| /****************/ | ||
| comment-object: | ||
| type: basic | ||
| output: {q: 123} | ||
| input: /**/{/**/q/**/:/**/123/**/,/**/}// | ||
| # Whitespace | ||
| # ---------- | ||
| ws-no-whitespace: | ||
| type: basic | ||
| output: {"foo":bar,bar:["qwe",null,[],{}],"baz":123} | ||
| input: '{foo:"bar","bar":["qwe",null,[],{}],"baz":123}' | ||
| ws-allow-prefix: | ||
| type: basic | ||
| output: 123 | ||
| input: " \t123" | ||
| ws-unicode-spaces: | ||
| type: advanced | ||
| output: { foo : 123 } | ||
| input: " | ||
| \u0020\u00A0\uFEFF | ||
| { | ||
| \x09\x0A\x0B\x0C\x0D\u1680\u180E | ||
| foo | ||
| \u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A | ||
| : | ||
| \u2028\u2029\u202F\u205F\u3000 | ||
| 123 | ||
| \uFEFF | ||
| }" | ||
| ws-unicode-newlines: | ||
| type: advanced | ||
| output: [ 123, 456 ] | ||
| input: " | ||
| [ | ||
| \u000D | ||
| 123, | ||
| \u2028 | ||
| 456, | ||
| \u2029 | ||
| ] | ||
| " | ||
| # Multiple tokens | ||
| # --------------- | ||
| multi-string-nospace: | ||
| type: basic | ||
| output: !error | ||
| input: '"foo""bar"' | ||
| multi-string: | ||
| type: basic | ||
| output: !error | ||
| input: '"foo" "bar"' | ||
| # note: valid javascript | ||
| multi-array: | ||
| type: extra | ||
| output: !error | ||
| input: '[0] [0]' | ||
| multi-object: | ||
| type: basic | ||
| output: !error | ||
| input: '{} {}' | ||
| ... |
| var _assert = require('assert') | ||
| var analyze = require('../').analyze | ||
| function addTest(a, b) { | ||
| if (typeof(describe) === 'function') { | ||
| it('test_analyze: ' + a + ' == ' + b, function() { | ||
| _assert.equal(a, b) | ||
| }) | ||
| } else { | ||
| _assert.equal(a, b) | ||
| } | ||
| } | ||
| var t = analyze(JSON.stringify(require('os').networkInterfaces())) | ||
| addTest(t.has_whitespace, false) | ||
| addTest(t.has_comments, false) | ||
| addTest(t.has_newlines, false) | ||
| addTest(t.newline, '\n') | ||
| addTest(t.quote, '"') | ||
| addTest(t.quote_keys, true) | ||
| addTest(t.indent, '') | ||
| var t = analyze(JSON.stringify(require('os').networkInterfaces(), null, 2)) | ||
| addTest(t.has_whitespace, true) | ||
| addTest(t.has_comments, false) | ||
| addTest(t.has_newlines, true) | ||
| addTest(t.newline, '\n') | ||
| addTest(t.quote, '"') | ||
| addTest(t.quote_keys, true) | ||
| addTest(t.indent, ' ') | ||
| var t = analyze(JSON.stringify(require('os').networkInterfaces(), null, 3)) | ||
| addTest(t.indent, ' ') | ||
| var t = analyze(JSON.stringify(require('os').networkInterfaces(), null, '\t')) | ||
| addTest(t.indent, '\t') | ||
| var t = analyze(JSON.stringify(require('os').networkInterfaces(), null, 3).replace(/\n/g, '\r\n')) | ||
| addTest(t.indent, ' ') | ||
| addTest(t.newline, '\r\n') | ||
| var t = analyze(JSON.stringify(require('os').networkInterfaces()).replace(/"/g, "'")) | ||
| addTest(t.quote, "'") | ||
| addTest(t.quote_keys, true) | ||
| var t = analyze("{foo:'bar', 'bar':\"baz\", 'baz':\"quux\"}") | ||
| addTest(t.quote, "'") | ||
| addTest(t.quote_keys, false) | ||
| var t = analyze("{foo:'bar', \"bar\":'baz', \"baz\":\"quux\"}") | ||
| addTest(t.quote, '"') | ||
| addTest(t.quote_keys, false) | ||
| var assert = require('assert') | ||
| var create = require('../lib/document').Document | ||
| var jju = require('..') | ||
| var str = '{ x\r\n:\n1, y: {"..z.": 123, t: null, s:"123", a:[ 1,2,{x:3},] }}\n' | ||
| var d = create(str) | ||
| assert.equal(d + '', str) | ||
| assert.deepEqual(d.get(''), {x:1,y:{'..z.':123,t:null,s:'123',a:[1,2,{x:3}]}}) | ||
| assert.deepEqual(d.get('x'), 1) | ||
| assert.deepEqual(d.get('x.x'), undefined) | ||
| assert.deepEqual(d.get('x.x.x.x'), undefined) | ||
| assert.strictEqual(d.get('y.x'), undefined) | ||
| assert.deepEqual(d.get('y.s'), '123') | ||
| assert.strictEqual(d.get('y.t'), null) | ||
| assert.strictEqual(d.get('y.t.x'), undefined) | ||
| assert.equal(d.has(''), true) | ||
| assert.equal(d.has('x'), true) | ||
| assert.equal(d.has('x.x'), false) | ||
| assert.equal(d.has('x.x.x.x'), false) | ||
| assert.equal(d.has('y.x'), false) | ||
| assert.equal(d.has('y'), true) | ||
| assert.equal(d.has('y.s'), true) | ||
| assert.equal(d.has('y.t'), true) | ||
| assert.equal(d.has('a'), false) | ||
| // arrays | ||
| assert.deepEqual(d.get('y.a'), [1,2,{x:3}]) | ||
| assert.deepEqual(d.get('y.a.0'), 1) | ||
| assert.deepEqual(d.get('y.a.2.x'), 3) | ||
| assert.deepEqual(d.get('y.a.10'), undefined) | ||
| assert.deepEqual(d.has('y.a.0'), true) | ||
| assert.deepEqual(d.has('y.a.10'), false) | ||
| assert.deepEqual(d.get('y.a.2'), {x:3}) | ||
| assert.deepEqual(d.get('y.a.-1'), undefined) | ||
| // controversial | ||
| assert.strictEqual(d.get('y.s.0'), undefined) | ||
| assert.equal(d.has('y.s.0'), false) | ||
| // paths | ||
| assert.deepEqual(d.get([]), {x:1,y:{'..z.':123,t:null,s:'123',a:[1,2,{x:3}]}}) | ||
| assert.strictEqual(d.has([]), true) | ||
| assert.strictEqual(d.get(['y','..z.']), 123) | ||
| assert.strictEqual(d.has(['y','..z.']), true) | ||
| assert.deepEqual(d.get(['y','a',2,'x']), 3) | ||
| assert.deepEqual(create('[1]').set(0, 4).get(''), [4]) | ||
| assert.deepEqual(create('[1]').set(1, 4).get(''), [1,4]) | ||
| assert.deepEqual(create('[1]').has(0), true) | ||
| assert.deepEqual(create('[1]').has(1), false) | ||
| assert.deepEqual(create('[1]').get(0), 1) | ||
| // invalid paths | ||
| assert.throws(function() { create('[1]').set(null, 4) }, /invalid path type/i) | ||
| assert.throws(function() { create('[1]').set({}, 4) }, /invalid path type/i) | ||
| assert.throws(function() { create('[1]').set(/./, 4) }, /invalid path type/i) | ||
| assert.throws(function() { create('[1]').set(function(){}, 4) }, /invalid path type/i) | ||
| assert.throws(function() { create('[1]').set(false, 4) }, /invalid path type/i) | ||
| assert.throws(function() { create('[1]').set(undefined, 4) }, /invalid path type/i) | ||
| // set root | ||
| assert.strictEqual(create(str).set('', 4).get(''), 4) | ||
| assert.strictEqual(create(str).set('', null).get(''), null) | ||
| assert.strictEqual(create(str).set('', {x:4}).get('x'), 4) | ||
| assert.deepEqual(create(str).set('', [1,2,3]).get(''), [1,2,3]) | ||
| assert.strictEqual(create('1').set('', 4).get(''), 4) | ||
| assert.strictEqual(create('null').set('', 4).get(''), 4) | ||
| assert.strictEqual(create('[]').set('', 4).get(''), 4) | ||
| assert.strictEqual(create('{}').set('', 4).get(''), 4) | ||
| // set 1st level | ||
| assert.deepEqual(create('{}').set('x', 4).get('x'), 4) | ||
| assert.deepEqual(create('{a:{b:[]}}').set('a.b.0', 4).get('a'), {b:[4]}) | ||
| //assert.deepEqual(create('1').set('x', 4).get('x'), 4) | ||
| //assert.deepEqual(create('null').set('x', 4).get('x'), 4) | ||
| // array: boundaries | ||
| assert.strictEqual(create('[]').set('0', 4).get('0'), 4) | ||
| assert.strictEqual(create('[1,2,3]').set('2', 4).get('2'), 4) | ||
| assert.strictEqual(create('[1,2,3]').set('3', 4).get('3'), 4) | ||
| // various error cases | ||
| assert.throws(function() { create('1').set('x', 4) }, /set key .* of an non-object/) | ||
| assert.throws(function() { create('null').set('x', 4) }, /set key .* of an non-object/) | ||
| assert.throws(function() { create('[]').set('x', 4) }, /set key .* of an array/) | ||
| assert.throws(function() { create('""').set('x', 4) }, /set key .* of an non-object/) | ||
| assert.throws(function() { create('{}').set('x.x.x', 4) }, /set key .* of an non-object/) | ||
| assert.throws(function() { create('1').set('1', 4) }, /set key .* of an non-object/) | ||
| assert.throws(function() { create('null').set('1', 4) }, /set key .* of an non-object/) | ||
| assert.throws(function() { create('""').set('1', 4) }, /set key .* of an non-object/) | ||
| assert.throws(function() { create('[]').set('-1', 4) }, /set key .* of an array/) | ||
| assert.throws(function() { create('[]').set('1', 4) }, /set key .* out of bounds/) | ||
| assert.throws(function() { create('[1,2,3]').set('4', 4) }, /set key .* out of bounds/) | ||
| assert.throws(function() { create('{a:{b:[]}}').set('a.b.x', 4) }, /set key .* of an array/) | ||
| // unsetting stuff | ||
| assert.throws(function() { create('[]').unset('') }, /can't remove root document/) | ||
| // arrays: handling spaces correctly | ||
| assert.equal(create("[]").set(0,{})+"", '[{}]') | ||
| assert.equal(create("[0]").set(1,{})+"", '[0,{}]') | ||
| assert.equal(create("[0,]").set(1,{})+"", '[0,{},]') | ||
| assert.equal(create("[ ]").set(0,{})+"", '[{} ]') | ||
| assert.equal(create("[ 0 , ]").set(1,{})+"", '[ 0 , {}, ]') | ||
| assert.equal(create("[ 0 ]").set(1,{})+"", '[ 0, {} ]') | ||
| assert.equal(create("{}").set('y',{})+"", '{"y":{}}') | ||
| assert.equal(create("{x:1}").set('y',{})+"", '{x:1,y:{}}') | ||
| assert.equal(create("{x:1,}").set('y',{})+"", '{x:1,y:{},}') | ||
| assert.equal(create("{ }").set('y',{})+"", '{"y":{} }') | ||
| assert.equal(create("{ x:1 , }").set('y',{})+"", '{ x:1 , y:{}, }') | ||
| assert.equal(create("{ x:1 }").set('y',{})+"", '{ x:1, y:{} }') | ||
| // deleting elements | ||
| assert.throws(function() { create('[]').unset('0') }, /unset key .* out of bounds/) | ||
| assert.throws(function() { create('[1,2]').unset('2') }, /unset key .* out of bounds/) | ||
| assert.throws(function() { create('[1,2,3]').unset('0') }, /in the middle of an array/) | ||
| // CommonJS assert spec is "awesome" | ||
| assert.deepEqual(create('[1,2]').unset('1').get(''), [1]) | ||
| assert.deepEqual(create('[1,2]').unset('1').get('').length, 1) | ||
| assert.deepEqual(create('[1,2,3]').unset('2').unset('1').get(''), [1]) | ||
| assert.deepEqual(create('[1,2,3]').unset('2').unset('1').get('').length, 1) | ||
| assert.deepEqual(create('[1]').unset('0').get(''), []) | ||
| assert.deepEqual(create('[1]').unset('0').get('').length, 0) | ||
| assert.deepEqual(create('{x:{y:"z"}, z:4}').unset('x').get(''), {z:4}) | ||
| assert.throws(function() { create('[1,2]').unset('') }, /root/) | ||
| // getting crazy | ||
| //assert.deepEqual(create(str).set('a.b.c.d.e', 1).get('a'), {b:{c:{d:{e:1}}}}) | ||
| // update: arrays | ||
| assert.deepEqual(create("[1]").update([2,3])+"", '[2,3]') | ||
| assert.deepEqual(create("[1]").update([2,3,4])+"", '[2,3,4]') | ||
| assert.deepEqual(create("[]").update([2])+"", '[2]') | ||
| assert.deepEqual(create("[2]").update([])+"", '[]') | ||
| assert.deepEqual(create("[2,3,4]").update([2,3])+"", '[2,3]') | ||
| assert.deepEqual(create("[2,3,4]").update([])+"", '[]') | ||
| assert.deepEqual(create("[]").update([2,3,4])+"", '[2,3,4]') | ||
| assert.deepEqual(create(" /*zz*/ [ 2 , 3 , 4 ] /*xx*/ ").update([])+"", ' /*zz*/ [ ] /*xx*/ ') | ||
| assert.deepEqual(create(" /*zz*/ [ ] /*xx*/ ").update([2,3,4])+"", ' /*zz*/ [2,3,4 ] /*xx*/ ') | ||
| // update: objects | ||
| assert.deepEqual(create("{x:1}").update({x:1,y:2,z:3})+"", '{x:1,y:2,z:3}') | ||
| assert.deepEqual(create("{x:1}").update({x:2,z:3,t:4})+"", '{x:2,z:3,t:4}') | ||
| assert.deepEqual(create("{}").update({x:1,y:2})+"", '{"x":1,"y":2}') | ||
| assert.deepEqual(create("{x:1}").update({})+"", '{}') | ||
| assert.deepEqual(create("{x:1,y:2}").update({x:1})+"", '{x:1}') | ||
| assert.deepEqual(create(" /*zz*/ { x /*a*/ : /*b*/ 2 , y:3 , z //\n: 4 } /*xx*/ ").update({})+"", ' /*zz*/ { } /*xx*/ ') | ||
| assert.deepEqual(create(" /*zz*/ { } /*xx*/ ").update({x: 2, y: 3, z: 4})+"", ' /*zz*/ {"x":2,"y":3,"z":4 } /*xx*/ ') | ||
| // remove trailing comma | ||
| assert.deepEqual(create("{x:1,}").update({})+"", '{}') | ||
| assert.deepEqual(create("[0,]").update([])+"", '[]') | ||
| assert.deepEqual(create("[0 /*z*/ , /*z*/]").update([])+"", '[ /*z*/]') | ||
| // mode | ||
| assert.equal(create('{"test":123}', {mode:'json'}).update({q:1,w:2})+'', '{"q":1,"w":2}') | ||
| assert.equal(create('{1:2}').update({ a: 1, b: [1,2], c: 3})+'', '{a:1,b:[1,2],c:3}') | ||
| // undef | ||
| //assert.throws(function(){ jju.update(undefined, undefined) }, /root doc/) | ||
| assert.equal(jju.update(undefined, undefined), '') | ||
| assert.equal(jju.update(undefined, 42), '42') | ||
| assert.equal(jju.update(undefined, {x: 5}), '{"x":5}') | ||
| /* | ||
| * real test | ||
| */ | ||
| var upd = { name: 'yapm', | ||
| version: '0.6.0', | ||
| description: 'npm wrapper allowing to use package.yaml instead of package.json', | ||
| author: { name: 'Alex Kocharin', email: 'alex@kocharin.ru' }, | ||
| keywords: | ||
| [ 'package manager', | ||
| 'modules', | ||
| 'install', | ||
| 'package.yaml', | ||
| 'package.json5', | ||
| 'yaml', | ||
| 'json5', | ||
| 'npm' ], | ||
| preferGlobal: true, | ||
| homepage: 'https://npmjs.org/doc/', | ||
| repository: { type: 'git', url: 'https://github.com/rlidwka/yapm' }, | ||
| bugs: { url: 'http://github.com/rlidwka/yapm/issues' }, | ||
| main: './yapm.js', | ||
| bin: { yapm: './yapm.js' }, | ||
| dependencies: { npm: '*', 'js-yaml': '*', through: '*', 'json5-utils': '*' }, | ||
| devDependencies: { async: '*' }, | ||
| optionalDependencies: { 'yaml-update': '*' }, | ||
| test_nonascii: 'тест' } | ||
| assert.deepEqual(create(create('{"garbage":"garbage"}').update(upd)).get(''), upd) | ||
| assert.deepEqual(JSON.parse(create('{"garbage":"garbage"}', {mode:'json',legacy:true}).update(upd)), upd) | ||
| //console.log(create('{"garbage":"garbage"}').update(upd)+'') | ||
| //assert.deepEqual(create(" [ ] //").set(0,{})+"" [ ,{}] // | ||
| //node -e 'console.log(require("./document").Document("{}").set("",[1,2,3])+"")'[1, 2, 3] | ||
| //alex@elu:~/json5-utils/lib$ node -e 'console.log(require("./document").Document("[]").set("0",[1,2,3]).get(""))' | ||
| //[ [ 1, 2, 3 ] ] | ||
| /*assert.equal(create('"test"').get(''), 'test') | ||
| assert.equal(create('"test"').get([]), 'test') | ||
| assert.equal(create('"test"').get(false), 'test') | ||
| assert.equal(create(undefined).get(''), undefined) | ||
| //assert.equal(create('"test"').set('', 'foo').toString(), '"foo"') | ||
| */ |
| var assert = require('assert') | ||
| var parse = require('../').parse | ||
| function addTest(arg, row, col, errRegExp) { | ||
| var fn = function() { | ||
| try { | ||
| parse(arg) | ||
| } catch(err) { | ||
| if (row !== undefined) assert.equal(err.row, row, 'wrong row: ' + err.row) | ||
| if (col !== undefined) assert.equal(err.column, col, 'wrong column: ' + err.column) | ||
| if (errRegExp) assert(errRegExp.exec(err.message)) | ||
| return | ||
| } | ||
| throw Error("no error") | ||
| } | ||
| if (typeof(describe) === 'function') { | ||
| it('test_errors: ' + JSON.stringify(arg), fn) | ||
| } else { | ||
| fn() | ||
| } | ||
| } | ||
| // semicolon will be unexpected, so it indicates an error position | ||
| addTest(';', 1, 1) | ||
| addTest('\n\n\n;', 4, 1) | ||
| addTest('\r\n;', 2, 1) | ||
| addTest('\n\r;', 3, 1) | ||
| addTest('\n\u2028;', 3, 1) | ||
| addTest('\n\u2029;', 3, 1) | ||
| addTest('[\n1\n,\n;', 4, 1) | ||
| addTest('{\n;', 2, 1) | ||
| addTest('{\n1\n:\n;', 4, 1) | ||
| addTest('.e3', 1, 3, /"\.e3"/) | ||
| // line continuations | ||
| addTest('["\\\n",\n;', 3, 1) | ||
| addTest('["\\\r\n",\n;', 3, 1) | ||
| addTest('["\\\u2028",\n;', 3, 1) | ||
| addTest('["\\\u2029",\n;', 3, 1) | ||
| // bareword rewind | ||
| addTest('nulz', 1, 1) | ||
| // no data | ||
| addTest(' ', 1, 3, /No data.*whitespace/) | ||
| addTest('blah', 1, 1, /Unexpected token 'b'/) | ||
| addTest('', 1, 1, /No data.*empty input/) | ||
| try { | ||
| parse('{{{{{{{{{') | ||
| } catch(err) { | ||
| var x = err.stack.match(/parseObject/g) | ||
| assert(!x || x.length < 2, "shouldn't blow up the stack with internal calls") | ||
| } | ||
| var assert = require('assert') | ||
| var parse = require('../').parse | ||
| function addTest(arg, bulk) { | ||
| function fn_json5() { | ||
| //console.log('testing: ', arg) | ||
| try { | ||
| var x = parse(arg) | ||
| } catch(err) { | ||
| x = 'fail' | ||
| } | ||
| try { | ||
| var z = eval('(function(){"use strict"\nreturn ('+String(arg)+'\n)\n})()') | ||
| } catch(err) { | ||
| z = 'fail' | ||
| } | ||
| assert.deepEqual(x, z) | ||
| } | ||
| function fn_strict() { | ||
| //console.log('testing: ', arg) | ||
| try { | ||
| var x = parse(arg, {mode: 'json'}) | ||
| } catch(err) { | ||
| x = 'fail' | ||
| } | ||
| try { | ||
| var z = JSON.parse(arg) | ||
| } catch(err) { | ||
| z = 'fail' | ||
| } | ||
| assert.deepEqual(x, z) | ||
| } | ||
| if (typeof(describe) === 'function' && !bulk) { | ||
| it('test_parse_json5: ' + JSON.stringify(arg), fn_json5) | ||
| it('test_parse_strict: ' + JSON.stringify(arg), fn_strict) | ||
| } else { | ||
| fn_json5() | ||
| fn_strict() | ||
| } | ||
| } | ||
| addTest('"\\uaaaa\\u0000\\uFFFF\\uFaAb"') | ||
| addTest(' "\\xaa\\x00\xFF\xFa\0\0" ') | ||
| addTest('"\\\'\\"\\b\\f\\t\\n\\r\\v"') | ||
| addTest('"\\q\\w\\e\\r\\t\\y\\\\i\\o\\p\\[\\/\\\\"') | ||
| addTest('"\\\n\\\r\n\\\n"') | ||
| addTest('\'\\\n\\\r\n\\\n\'') | ||
| addTest(' null') | ||
| addTest('true ') | ||
| addTest('false') | ||
| addTest(' Infinity ') | ||
| addTest('+Infinity') | ||
| addTest('[]') | ||
| addTest('[ 0xA2, 0X024324AaBf]') | ||
| addTest('-0x12') | ||
| addTest(' [1,2,3,4,5]') | ||
| addTest('[1,2,3,4,5,] ') | ||
| addTest('[1e-13]') | ||
| addTest('[null, true, false]') | ||
| addTest(' [1,2,"3,4,",5,]') | ||
| addTest('[ 1,\n2,"3,4," \r\n,\n5,]') | ||
| addTest('[ 1 , 2 , 3 , 4 , 5 , ]') | ||
| addTest('{} ') | ||
| addTest('{"2":1,"3":null,}') | ||
| addTest('{ "2 " : 1 , "3":null , }') | ||
| addTest('{ \"2\" : 25e245 , \"3\": 23 }') | ||
| addTest('{"2":1,"3":nul,}') | ||
| addTest('{:1,"3":nul,}') | ||
| addTest('[1,2] // ssssssssss 3,4,5,] ') | ||
| addTest('[1,2 , // ssssssssss \n//xxx\n3,4,5,] ') | ||
| addTest('[1,2 /* ssssssssss 3,4,*/ /* */ , 5 ] ') | ||
| addTest('[1,2 /* ssssssssss 3,4,*/ /* * , 5 ] ') | ||
| addTest('{"3":1,"3":,}') | ||
| addTest('{ чйуач:1, щцкшчлм : 4,}') | ||
| addTest('{ qef-:1 }') | ||
| addTest('{ $$$:1 , ___: 3}') | ||
| addTest('{3:1,2:1}') | ||
| addTest('{3.4e3:1}') | ||
| addTest('{-3e3:1}') | ||
| addTest('{+3e3:1}') | ||
| addTest('{.3e3:1}') | ||
| for (var i=0; i<200; i++) { | ||
| addTest('"' + String.fromCharCode(i) + '"', true) | ||
| } | ||
| // strict JSON test cases | ||
| addTest('"\\xaa"') | ||
| addTest('"\\0"') | ||
| addTest('"\0"') | ||
| addTest('"\\v"') | ||
| addTest('{null: 123}') | ||
| addTest("{'null': 123}") | ||
| assert.throws(function() { | ||
| parse('0o') | ||
| }) | ||
| assert.strictEqual(parse('01234567'), 342391) | ||
| assert.strictEqual(parse('0o1234567'), 342391) | ||
| // undef | ||
| assert.strictEqual(parse(undefined), undefined) | ||
| // whitespaces | ||
| addTest('[1,\r\n2,\r3,\n]') | ||
| '\u0020\u00A0\uFEFF\x09\x0A\x0B\x0C\x0D\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000'.split('').forEach(function(x) { | ||
| addTest(x+'[1,'+x+'2]'+x) | ||
| addTest('"'+x+'"'+x) | ||
| }) | ||
| '\u000A\u000D\u2028\u2029'.split('').forEach(function(x) { | ||
| addTest(x+'[1,'+x+'2]'+x) | ||
| addTest('"\\'+x+'"'+x) | ||
| }) | ||
| /* weird ES6 stuff, not working | ||
| if (process.version > 'v0.11.7') { | ||
| assert(Array.isArray(parse('{__proto__:[]}').__proto__)) | ||
| assert.equal(parse('{__proto__:{xxx:5}}').xxx, undefined) | ||
| assert.equal(parse('{__proto__:{xxx:5}}').__proto__.xxx, 5) | ||
| var o1 = parse('{"__proto__":[]}') | ||
| assert.deepEqual([], o1.__proto__) | ||
| assert.deepEqual(["__proto__"], Object.keys(o1)) | ||
| assert.deepEqual([], Object.getOwnPropertyDescriptor(o1, "__proto__").value) | ||
| assert.deepEqual(["__proto__"], Object.getOwnPropertyNames(o1)) | ||
| assert(o1.hasOwnProperty("__proto__")) | ||
| assert(Object.prototype.isPrototypeOf(o1)) | ||
| // Parse a non-object value as __proto__. | ||
| var o2 = JSON.parse('{"__proto__":5}') | ||
| assert.deepEqual(5, o2.__proto__) | ||
| assert.deepEqual(["__proto__"], Object.keys(o2)) | ||
| assert.deepEqual(5, Object.getOwnPropertyDescriptor(o2, "__proto__").value) | ||
| assert.deepEqual(["__proto__"], Object.getOwnPropertyNames(o2)) | ||
| assert(o2.hasOwnProperty("__proto__")) | ||
| assert(Object.prototype.isPrototypeOf(o2)) | ||
| }*/ | ||
| assert.throws(parse.bind(null, "{-1:42}")) | ||
| for (var i=0; i<100; i++) { | ||
| var str = '-01.e'.split('') | ||
| var rnd = [1,2,3,4,5].map(function(x) { | ||
| x = ~~(Math.random()*str.length) | ||
| return str[x] | ||
| }).join('') | ||
| try { | ||
| var x = parse(rnd) | ||
| } catch(err) { | ||
| x = 'fail' | ||
| } | ||
| try { | ||
| var y = JSON.parse(rnd) | ||
| } catch(err) { | ||
| y = 'fail' | ||
| } | ||
| try { | ||
| var z = eval(rnd) | ||
| } catch(err) { | ||
| z = 'fail' | ||
| } | ||
| //console.log(rnd, x, y, z) | ||
| if (x !== y && x !== z) throw 'ERROR' | ||
| } | ||
| var assert = require('assert') | ||
| var FS = require('fs') | ||
| var YAML = require('js-yaml') | ||
| var jju = require('../') | ||
| function addTest(name, fn) { | ||
| if (typeof(describe) === 'function') { | ||
| it(name, fn) | ||
| } else { | ||
| fn() | ||
| } | ||
| } | ||
| var schema = YAML.Schema.create([ | ||
| new YAML.Type('!error', { | ||
| kind: 'scalar', | ||
| resolve: function (state) { | ||
| //state.result = null | ||
| return true | ||
| }, | ||
| }) | ||
| ]) | ||
| var tests = YAML.safeLoad(FS.readFileSync(__dirname + '/portable-json5-tests.yaml', 'utf8'), { | ||
| schema: schema | ||
| }) | ||
| if (!Object.is) { | ||
| Object.defineProperty(Object, 'is', { | ||
| value: function(x, y) { | ||
| if (x === y) { | ||
| return x !== 0 || 1 / x === 1 / y; | ||
| } | ||
| return x !== x && y !== y; | ||
| }, | ||
| configurable: true, | ||
| enumerable: false, | ||
| writable: true, | ||
| }) | ||
| } | ||
| for (var k in tests) { | ||
| ;(function(k) { | ||
| addTest(k, function() { | ||
| try { | ||
| var result = jju.parse(tests[k].input) | ||
| } catch(err) { | ||
| result = null | ||
| } | ||
| // need deepStrictEqual | ||
| if (typeof(result) === 'object') { | ||
| assert.deepEqual(result, tests[k].output) | ||
| } else { | ||
| assert(Object.is(result, tests[k].output), String(result) + ' == ' + tests[k].output) | ||
| } | ||
| }) | ||
| })(k) | ||
| } | ||
| var assert = require('assert') | ||
| var parse = require('../').parse | ||
| var stringify = require('../').stringify | ||
| function deepEqual(x, y) { | ||
| if (Number.isNaN(x)) { | ||
| return assert(Number.isNaN(y)) | ||
| } | ||
| assert.deepEqual(x, y) | ||
| } | ||
| function addTest(arg, arg2, arg3) { | ||
| function fn() { | ||
| deepEqual(parse(stringify(arg)), arg2 === undefined ? arg : arg2) | ||
| if (arg !== undefined) deepEqual(JSON.parse(stringify(arg, {mode: 'json', indent: false})), (arg3 === undefined ? (arg2 === undefined ? arg : arg2) : arg3)) | ||
| } | ||
| if (typeof(describe) === 'function') { | ||
| it('test_stringify: ' + JSON.stringify(arg), fn) | ||
| } else { | ||
| fn() | ||
| } | ||
| } | ||
| addTest(0) | ||
| addTest(-0) | ||
| addTest(NaN, undefined, null) | ||
| addTest(Infinity, undefined, null) | ||
| addTest(-Infinity, undefined, null) | ||
| addTest(123) | ||
| addTest(19508130958019385.135135) | ||
| addTest(-2e123) | ||
| addTest(null) | ||
| addTest(undefined) | ||
| addTest([]) | ||
| addTest([,,,,,,,], [null,null,null,null,null,null,null]) | ||
| addTest([undefined,null,1,2,3,], [null,null,1,2,3]) | ||
| addTest([[[[]]],[[]]]) | ||
| addTest({}) | ||
| addTest({1:2,3:4}) | ||
| addTest({1:{1:{1:{1:4}}}, 3:4}) | ||
| addTest({1:undefined, 3:undefined}, {}) | ||
| addTest(new Number(4), 4) | ||
| addTest(new Boolean(true), true) | ||
| addTest(new String('xqefxef'), 'xqefxef') | ||
| addTest(new Boolean(), false) | ||
| var r='';for (var i=0; i<5000; i++) {r+=String.fromCharCode(i)} | ||
| addTest(r) | ||
| assert.equal("[1, 2, 3]", stringify([1, 2, 3], {indent: 1})) | ||
| assert.equal("[1, 2, 3]", stringify([1, 2, 3], {indent: 2})) | ||
| var oddball = Object(42) | ||
| oddball.__proto__ = { __proto__: null } | ||
| assert.equal('{}', stringify(oddball)) | ||
| /* this WILL throw | ||
| var falseNum = Object("37") | ||
| falseNum.__proto__ = Number.prototype | ||
| assert.equal("{0: '3', 1: '7'}", stringify(falseNum))*/ | ||
| assert.equal(stringify(Infinity), 'Infinity') | ||
| assert.equal(stringify(Infinity, {mode: 'json'}), 'null') | ||
| assert.equal(stringify(NaN), 'NaN') | ||
| assert.equal(stringify(NaN, {mode: 'json'}), 'null') | ||
| assert.equal(stringify(-0), '-0') | ||
| assert.equal(stringify('test', null), "'test'") | ||
| var array = [""] | ||
| var expected = "''" | ||
| for (var i = 0; i < 1000; i++) { | ||
| array.push("") | ||
| expected = "''," + expected | ||
| } | ||
| expected = '[' + expected + ']' | ||
| assert.equal(expected, stringify(array, {indent: false})) | ||
| assert.strictEqual(stringify([1,2,3], function(){}), undefined) | ||
| // don't stringify prototype | ||
| assert.equal('{a: 1}', stringify({a:1,__proto__:{b:2}})) | ||
| // sort keys tests | ||
| assert.equal('{a: 1, b: 2, z: 3}', stringify({b:2,a:1,z:3}, {sort_keys: 1})) | ||
| assert.equal('{a: 1, b: {a: 2, b: 5, c: 1}, z: 3}', stringify({b:{c:1,a:2,b:5},a:1,z:3}, {sort_keys: 1})) | ||
| assert.equal('{a: [3, 5, 1], b: 2, z: 3}', stringify({b:2,a:[3,5,1],z:3}, {sort_keys: 1})) | ||
| assert.equal('{b: 2, a: 1, z: 3}', stringify({b:2,a:1,z:3}, {sort_keys: 0})) |
| var assert = require('assert') | ||
| var parse = require('../').parse | ||
| function tokenize(arg) { | ||
| var result = [] | ||
| parse(arg, {_tokenize: function(smth) { | ||
| result.push(smth) | ||
| }}) | ||
| assert.deepEqual(result.map(function(x){return x.raw}).join(''), arg) | ||
| return result | ||
| } | ||
| function addTest(x, exp) { | ||
| function fn(){assert.deepEqual(tokenize(x), exp)} | ||
| if (typeof(describe) === 'function') { | ||
| it('test_tokenize: ' + JSON.stringify(x), fn) | ||
| } else { | ||
| fn() | ||
| } | ||
| } | ||
| addTest('123', [ { raw: '123', value: 123, type: 'literal', stack: [] }]) | ||
| addTest(' /* zz */\r\n true /* zz */\n', | ||
| [ { raw: ' ', type: 'whitespace', stack: [] }, | ||
| { raw: '/* zz */', type: 'comment', stack: [] }, | ||
| { raw: '\r\n', type: 'newline', stack: [] }, | ||
| { raw: ' ', type: 'whitespace', stack: [] }, | ||
| { raw: 'true', type: 'literal', value: true, stack: [] }, | ||
| { raw: ' ', type: 'whitespace', stack: [] }, | ||
| { raw: '/* zz */', type: 'comment', stack: [] }, | ||
| { raw: '\n', type: 'newline', stack: [] } ]) | ||
| addTest('{q:123, w : /*zz*/\n\r 345 } ', | ||
| [ { raw: '{', type: 'separator', stack: [] }, | ||
| { raw: 'q', type: 'key', value: 'q', stack: [] }, | ||
| { raw: ':', type: 'separator', stack: [] }, | ||
| { raw: '123', type: 'literal', value: 123, stack: ['q'] }, | ||
| { raw: ',', type: 'separator', stack: [] }, | ||
| { raw: ' ', type: 'whitespace', stack: [] }, | ||
| { raw: 'w', type: 'key', value: 'w', stack: [] }, | ||
| { raw: ' ', type: 'whitespace', stack: [] }, | ||
| { raw: ':', type: 'separator', stack: [] }, | ||
| { raw: ' ', type: 'whitespace', stack: [] }, | ||
| { raw: '/*zz*/', type: 'comment', stack: [] }, | ||
| { raw: '\n', type: 'newline', stack: [] }, | ||
| { raw: '\r', type: 'newline', stack: [] }, | ||
| { raw: ' ', type: 'whitespace', stack: [] }, | ||
| { raw: '345', type: 'literal', value: 345, stack: ['w'] }, | ||
| { raw: ' ', type: 'whitespace', stack: [] }, | ||
| { raw: '}', type: 'separator', stack: [] }, | ||
| { raw: ' ', type: 'whitespace', stack: [] } ]) | ||
| addTest('null /* */// xxx\n//xxx', | ||
| [ { raw: 'null', type: 'literal', value: null, stack: [] }, | ||
| { raw: ' ', type: 'whitespace', stack: [] }, | ||
| { raw: '/* */', type: 'comment', stack: [] }, | ||
| { raw: '// xxx', type: 'comment', stack: [] }, | ||
| { raw: '\n', type: 'newline', stack: [] }, | ||
| { raw: '//xxx', type: 'comment', stack: [] } ]) | ||
| addTest('[1,2,[[],[1]],{},{1:2},{q:{q:{}}},]', | ||
| [ { raw: '[', type: 'separator', stack: [] }, | ||
| { raw: '1', type: 'literal', value: 1, stack: [0] }, | ||
| { raw: ',', type: 'separator', stack: [] }, | ||
| { raw: '2', type: 'literal', value: 2, stack: [1] }, | ||
| { raw: ',', type: 'separator', stack: [] }, | ||
| { raw: '[', type: 'separator', stack: [2] }, | ||
| { raw: '[', type: 'separator', stack: [2,0] }, | ||
| { raw: ']', type: 'separator', stack: [2,0] }, | ||
| { raw: ',', type: 'separator', stack: [2] }, | ||
| { raw: '[', type: 'separator', stack: [2,1] }, | ||
| { raw: '1', type: 'literal', value: 1, stack: [2,1,0] }, | ||
| { raw: ']', type: 'separator', stack: [2,1] }, | ||
| { raw: ']', type: 'separator', stack: [2] }, | ||
| { raw: ',', type: 'separator', stack: [] }, | ||
| { raw: '{', type: 'separator', stack: [3] }, | ||
| { raw: '}', type: 'separator', stack: [3] }, | ||
| { raw: ',', type: 'separator', stack: [] }, | ||
| { raw: '{', type: 'separator', stack: [4] }, | ||
| { raw: '1', type: 'key', value: 1, stack: [4] }, | ||
| { raw: ':', type: 'separator', stack: [4] }, | ||
| { raw: '2', type: 'literal', value: 2, stack: [4,'1'] }, | ||
| { raw: '}', type: 'separator', stack: [4] }, | ||
| { raw: ',', type: 'separator', stack: [] }, | ||
| { raw: '{', type: 'separator', stack: [5] }, | ||
| { raw: 'q', type: 'key', value: 'q', stack: [5] }, | ||
| { raw: ':', type: 'separator', stack: [5] }, | ||
| { raw: '{', type: 'separator', stack: [5,'q'] }, | ||
| { raw: 'q', type: 'key', value: 'q', stack: [5,'q'] }, | ||
| { raw: ':', type: 'separator', stack: [5,'q'] }, | ||
| { raw: '{', type: 'separator', stack: [5,'q','q'] }, | ||
| { raw: '}', type: 'separator', stack: [5,'q','q'] }, | ||
| { raw: '}', type: 'separator', stack: [5,'q'] }, | ||
| { raw: '}', type: 'separator', stack: [5] }, | ||
| { raw: ',', type: 'separator', stack: [] }, | ||
| { raw: ']', type: 'separator', stack: [] } ]) | ||
| var assert = require('assert') | ||
| var FS = require('fs') | ||
| var YAML = require('js-yaml') | ||
| var jju = require('../') | ||
| function addTest(name, fn) { | ||
| if (typeof(describe) === 'function') { | ||
| it(name, fn) | ||
| } else { | ||
| fn() | ||
| } | ||
| } | ||
| FS.readdirSync(__dirname + '/update').filter(function(file) { | ||
| return file.match(/^[^\.].*\.yaml$/) | ||
| }).forEach(function(file) { | ||
| addTest('update: ' + file, function() { | ||
| var test = YAML.load(FS.readFileSync(__dirname + '/update/' + file, 'utf8')) | ||
| assert.strictEqual(test.test(jju, test.input), test.output) | ||
| }) | ||
| }) | ||
| input: | | ||
| { "name": "just-a-demo", | ||
| "version": "0.1.2", | ||
| "description": "blahblahblah", | ||
| "main": "test.js", | ||
| "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, | ||
| "author": "John Doe <whoever@google.com>", | ||
| "license": "BSD-2-Clause" } | ||
| output: | | ||
| { "name": "just-a-demo", | ||
| "version": "0.1.2", | ||
| "description": "blahblahblah", | ||
| "main": "test.js", | ||
| "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, | ||
| "author": { | ||
| "name": "John Doe", | ||
| "email": "whoever@google.com" | ||
| }, | ||
| "license": "BSD-2-Clause" } | ||
| test: !!js/function | | ||
| function(jju, input) { | ||
| obj = jju.parse(input) | ||
| obj.author = { | ||
| name: 'John Doe', | ||
| email: 'whoever@google.com', | ||
| } | ||
| return jju.update(input, obj) | ||
| } | ||
| input: | | ||
| { | ||
| "foo": { | ||
| "bar": { | ||
| "baz": { | ||
| "quux": "4" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| output: | | ||
| { | ||
| "foo": { | ||
| "bar": { | ||
| "baz": { | ||
| "quux": "4" | ||
| }, | ||
| "qwe": { | ||
| "rty": { | ||
| "aaa": { | ||
| "bbb": 1 | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| test: !!js/function | | ||
| function(jju, input) { | ||
| obj = jju.parse(input) | ||
| obj.foo.bar.qwe = {rty: {aaa: {bbb: 1}}} | ||
| return jju.update(input, obj, {mode:'json'}) | ||
| } | ||
| input: | | ||
| { | ||
| "name": "test", | ||
| "version": "0.0.0", | ||
| "dependencies": { | ||
| "foo": "1.2.x", | ||
| "bar": ">= 1" | ||
| }, | ||
| "bundleDependencies": [ | ||
| "foo", | ||
| "bar" | ||
| ], | ||
| "license": "BSD-2-Clause" | ||
| } | ||
| output: | | ||
| { | ||
| "name": "test", | ||
| "version": "0.0.0", | ||
| "dependencies": { | ||
| "foo": "1.2.x" | ||
| }, | ||
| "bundleDependencies": [ | ||
| "foo" | ||
| ], | ||
| "license": "BSD-2-Clause" | ||
| } | ||
| test: !!js/function | | ||
| function(jju, input) { | ||
| obj = jju.parse(input) | ||
| obj.bundleDependencies.pop() | ||
| delete obj.dependencies.bar | ||
| return jju.update(input, obj, {mode:'json'}) | ||
| } | ||
| input: | | ||
| { | ||
| "name": "test", | ||
| "version": "0.0.0", | ||
| "bundleDependencies": [ | ||
| "foo", | ||
| "bar" | ||
| ], | ||
| "license": "BSD-2-Clause" | ||
| } | ||
| output: | | ||
| { | ||
| "name": "test", | ||
| "version": "0.0.0", | ||
| "bundleDependencies": [ | ||
| "foo", | ||
| "bar", | ||
| "baz", | ||
| "quux" | ||
| ], | ||
| "license": "BSD-2-Clause" | ||
| } | ||
| test: !!js/function | | ||
| function(jju, input) { | ||
| obj = jju.parse(input) | ||
| obj.bundleDependencies.push('baz') | ||
| obj.bundleDependencies.push('quux') | ||
| return jju.update(input, obj, {mode:'json'}) | ||
| } | ||
| input: | | ||
| { | ||
| "name": "test", | ||
| "version": "0.0.0", | ||
| "dependencies": { | ||
| "foobar": "*", | ||
| "bazquux": ">= 1.1.1" | ||
| }, | ||
| "license": "BSD-2-Clause" | ||
| } | ||
| output: | | ||
| { | ||
| "name": "test", | ||
| "version": "0.0.0", | ||
| "dependencies": { | ||
| "foobar": "*", | ||
| "bazquux": ">= 1.1.1", | ||
| "whatever": "1.2.x", | ||
| "qwerty": "1" | ||
| }, | ||
| "license": "BSD-2-Clause" | ||
| } | ||
| test: !!js/function | | ||
| function(jju, input) { | ||
| obj = jju.parse(input) | ||
| obj.dependencies.whatever = '1.2.x' | ||
| obj.dependencies.qwerty = '1' | ||
| return jju.update(input, obj, {mode:'json'}) | ||
| } | ||
| input: | | ||
| { "name":"npm-test-array-bin" | ||
| , "version":"1.2.5" | ||
| , "bin": [ "bin/array-bin" ] | ||
| , "scripts": { "test": "node test.js" } } | ||
| # less than ideal, I know... | ||
| output: | | ||
| { "name":"npm-test-array-bin" | ||
| , "version":"1.2.5" | ||
| , "bin": {"array-bin":"bin/array-bin"} | ||
| , "scripts": { "test": "node test.js" }, "readme": "just an npm test\n", "readmeFilename": "README", "description": "just an npm test", "_id": "npm-test-array-bin@1.2.5", "dist": {"shasum":"9c426a1bd55e98718ab4ddcc01fa57ea83c649f1"}, "_from": "npm-test-array-bin/" } | ||
| test: !!js/function | | ||
| function(jju, input) { | ||
| obj = | ||
| { name: 'npm-test-array-bin', | ||
| version: '1.2.5', | ||
| bin: { 'array-bin': 'bin/array-bin' }, | ||
| scripts: { test: 'node test.js' }, | ||
| readme: 'just an npm test\n', | ||
| readmeFilename: 'README', | ||
| description: 'just an npm test', | ||
| _id: 'npm-test-array-bin@1.2.5', | ||
| dist: { shasum: '9c426a1bd55e98718ab4ddcc01fa57ea83c649f1' }, | ||
| _from: 'npm-test-array-bin/' } | ||
| return jju.update(input, obj) | ||
| } | ||
| input: | | ||
| // vim:syntax=javascript | ||
| { | ||
| name: 'yapm', | ||
| version: '1.1.0-1325', // upstream npm@1.3.25 | ||
| description: 'A package manager for node (npm fork)', | ||
| } | ||
| output: | | ||
| // vim:syntax=javascript | ||
| { | ||
| name: 'yapm', | ||
| version: '1.1.0-1325', // upstream npm@1.3.25 | ||
| description: 'A package manager for node (npm fork)', | ||
| _id: 'yapm@1.1.0-1325', | ||
| dist: { | ||
| shasum: 'd5aa31c1ad00c1e7e57e07cea1b22c1806a47111', | ||
| }, | ||
| _from: './zzz', | ||
| } | ||
| test: !!js/function | | ||
| function(jju, input) { | ||
| var upd = { | ||
| "name": "yapm", | ||
| "version": "1.1.0-1325", | ||
| "description": "A package manager for node (npm fork)", | ||
| "_id": "yapm@1.1.0-1325", | ||
| "dist": { | ||
| "shasum": "d5aa31c1ad00c1e7e57e07cea1b22c1806a47111" | ||
| }, | ||
| "_from": "./zzz" | ||
| } | ||
| return jju.update(input, upd) | ||
| } | ||
Sorry, the diff of this file is not supported yet
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
1
-80%0
-100%69721
-44.64%11
-65.62%1597
-30.38%