Giter Club home page Giter Club logo

ion-js's Issues

Refactor: text lexer ERROR constant

A constant named "ERROR" is used as a sentinel value to indicate that the lexer (ParserTextRaw) is currently not holding on to a value, but this is confusing as this is a normal state after each call to next() and thus doesn't actually indicate any error. Should most likely be renamed to NONE

The one and only example showing how to use ion-js is broken.

From the main page at https://github.com/amzn/ion-js

var ionJs = require("ion-js")

var ionData = "{ hello: \"Ion\" }"; 
var ionReader = ionJs.makeReader(ionData); 
ionReader.next(); 
ionReader.stepIn(); 
ionReader.next(); 
var hello = ionReader.fieldName(); 
var ion = ionReader.stringValue(); 
ionReader.stepOut(); 
console.log(ion.concat(", ").concat(hello));

This is the output:

"ello: \"Ion, hello"

Pretty sure the output is supposed to be "Ion, hello"

Tested using:

  1. https://amzn.github.io/ion-js/browser/scripts/ion-bundle.min.js (recommended on the README)
  2. https://npm.runkit.com/ion-js ("Try it yourself" on the README)

Looks like parsing of strings inside of structs is broken:

var ionJs = require("ion-js");
var r = ionJs.makeReader('{key:"value"}');
r.next(); r.stepIn(); r.next();
console.log("fieldName: " + r.fieldName());
console.log("stringValue: " + r.stringValue());

// output:
"fieldName: key"
"stringValue: ey:\"value"

A more fluent way to create/write Ion

The API supported bu Ion-js mimics (it is inspired by) the other programming language libs for Ion.
it is a little verbose to use.

Devs tends to create their Ion data as a String in the native language and then pass that whole string to the lib to build the Ion Value. This makes it hard to catch errors in the input string.

Maybe provide a more fluent mechanism to create Ion values could be of more help.

Add NPM support

The code is close to but not exactly ready for a Node.js package. Finish this up and create a Node.js pacakge for IonJS

Match API to other implementations (ion-java, etc.)

Should take a quick peek at the terminology and API of, say, the Java implementation to ensure our readers and writers work similarly (in particular I'm thinking about entering and leaving containers).

Consistent interface for reading annotations

Currently IonTextReader exposes annotations via .annotations() (returns an Array), whereas IonBinaryReader exposes annotations via hasAnnotations() and getAnnotation(i) (returns the annotation at a specific index in the array).

Can these be unified into a common API on the Reader interface?

This might be relevant to #29.

Add ES5 suport

Current setup spits out ES6 .js files. Figure out how to get ES5 support going as well.

Refactor: T_STRING2

This type constant is unclear - what does the 2 refer to? Needs a better name

Provide translations from/to JSON

Even though there is data loss when translating from Ion to JSON, the ability to do so seems to be a good feature to have here. So adding operations that will allow

  • JSON->Ion
  • Ion ->JSON

as part of the API would be nice.

Refactor: makeReader API

I think I made a goof while introducing type safety and made the argument to makeReader() a Span. Ideally users should just have some data (string, number[], Buffer, etc.) and be able to pass it directly into makeReader() - we should do all the heavy lifting on our part to wrangle it into the correct Span type

Better tutorial with live coding

The current tutorial for using Ion inside the browser as a script (not as an npm package) is primitive.

The tutorial should walk through the basics of Ion and the manipulation of Ion values through Ion-js with inline runnable examples.

Text reader doesn't accept byte arrays of text anymore

I'm unsure if this is a regression or if it was never intended behavior in the first place.

Previously, passing text data as a byte array to makeReader would still return a functioning text reader. Now it throws an error:

var ionJs = require("ion-js")
var input = "{foo:bar}";
var arr = new Uint8Array(input.length)
// A more realistic example would be loading a text file from disk as a Buffer (node.js) or Blob (HTML5)
for (var i = 0; i < input.length; i++) arr[i] = input.charCodeAt(i)

var reader = ionJs.makeReader(arr);
console.log(reader.next().name);
TypeError: this._src.charCodeAt is not a function

2.0.0: https://runkit.com/embed/vz9xv8h87vqp
2.1.2: https://runkit.com/embed/ee8ubusq2qrx (contains more detailed stack trace)

Roundtrip testing

Added roundtrip tests to ensure that the library parses to the correct values.

Better documentation of implementation structure

  • UML diagram documenting interaction of files/objects/methods within the codebase.

  • Refactoring inheritance using JS equivalents of "Interfaces/classes" to allow typescript to ensure the contracts detailed in the UML. This allows for complete code coverage for contracts at runtime by the typescript compiler.

  • Explicit comments describing each file/piece of functionality as it is refactored.

Improve JavaScript version selection in tests

Currently we use a block of logic to select from a couple different version of JavaScript in our tests:

define([
'intern',
'intern!object',
'intern/chai!assert',
'dist/amd/es5/IonTests',
'dist/amd/es6/IonTests',
],
function(intern, registerSuite, assert, ionEs5, ionEs6) {
var ionVersions = {
es5: ionEs5,
es6: ionEs6,
};
var ion = ionVersions[intern.args.ionVersion];

A more clever way would be to have a module (tests/unit/Version.js) that encapsulates this switching logic:

define(
['intern', 'dist/amd/es5/IonTests', 'dist/amd/es6/IonTests'],
function(intern, ionEs5, ionEs6) {
var ionVersions = {
es5: ionEs5,
es6: ionEs6,
};
return ionVersions[intern.args.ionVersion];
}
);

Also, the "ionVersion" parameter name is misleading and should be changed.

With that module, the above switching logic is extracted away and our test includes are now simply:

define([
'intern!object',
'intern/chai!assert',
'tests/unit/Version',
],
function(registerSuite, assert, ion) {

Add travis support

Configure travis and integration builds for ion-js. Ensure that documentation and reporting are configured for public browsing through Github Pages.

Refactor: CH_DQ

The constant CH_DQ should be renamed to be CH_DOUBLE_QUOTE for clarity

Singly quoted symbols IonReader interpreting as type `string`

Reader seems to parse symbols given as JS strings with escaped single quotes as String instead of Symbol.

> require("ion-js").makeReader("\'sym\'").next()
IonType {
bid: 8,
name: 'string',
scalar: true,
lob: false,
num: false,
container: false }

The above should have yielded a Symbol not a String

Contrast the expected behavior with double quoted strings and bareword/identifier symbols:

> require("ion-js").makeReader("\"str\"").next()
IonType {
bid: 8,
name: 'string',
scalar: true,
lob: false,
num: false,
> require("ion-js").makeReader("identifier").next()
IonType {
bid: 7,
name: 'symbol',
scalar: true,
lob: false,
num: false,
container: false }

Regression in parsing quoted annotations

Code:

var reader = ionJs.makeReader("'quoted_annotation'::{}")
reader.next()
console.log(reader.annotations())
while (reader.annotations().shift()) ; // Workaround for separate bug of static instance

var reader = ionJs.makeReader("first::'second'::{}")
reader.next()
console.log(reader.annotations())

In 2.0.0 (behaves as expected): https://runkit.com/embed/4kzxn7to1c9f

["quoted_annotation"]
["first", "second"]

In 2.1.2 (latest): https://runkit.com/embed/lri33z6vznsp

["'quoted_annotation"]
["first", "irst::'second"]

Reader seems to accumulate annotations between invocations

Annotations should not accumulate between new instances of IonReader.

r = require("ion-js").makeReader("ann1a::ann1b::10 ann2::11"); r.next(); r.annotations()
[ 'ann1a', 'ann1b' ]
> r = require("ion-js").makeReader("ann1a::ann1b::10 ann2::11"); r.next(); r.annotations()
[ 'ann1a', 'ann1b', 'ann1a', 'ann1b' ]
> r = require("ion-js").makeReader("ann1a::ann1b::10 ann2::11"); r.next(); r.annotations()
[ 'ann1a', 'ann1b', 'ann1a', 'ann1b', 'ann1a', 'ann1b' ]

Should verify reader's beahviour when for the same reader instance we navigate to multiple values that have annotations. The API should return the annotations of the current value being pointed to by the reader.

ASM.js Optimizations

It may be worthwhile to leverage ASM.js for low-level serialization bits. This could be done as handcoded routines, or using some tooling. I'd imagine binary encoding/decoding could get some efficiency from this.

Tests for transformed JS code and packaged artifacts

Currently the Typescript code is used to generate

  • es6 code (this is what we currently run our tests against)
  • commonjs modules that create the npm package
  • minified es5 code for use in the browser

There are no automated tests on the resulting js code. The tools are pretty mature but still we should have automated tests such that

  • npm package is tested (pack, install and run)
  • minified js bundle is tested on browser(s)

Investigate separate set of exports for tests

Currently Ion.ts exports a bunch of classes just for test visibility. We may want to look into having two sets of exports, one for consumers and one for tests so that we're not leaking too many implementation details

Zulu timestamps fails with Error: Invalid decimal 00.000Z

Trying to parse 2017-05-01T01:01:00.000Z timestamp will fail with the following error.

Error: Invalid decimal 00.000Z
  at Function.parse  </Users/user/ion-js/src/IonDecimal.ts:188:12>
  at Function.parse  </Users/user/ion-js/src/IonTimestamp.ts:504:28>
  at Test.suite.(anonymous function) [as test]  <tests/unit/IonTimestampTest.js:26:23>

Document Implementation Limitations

We should be explicit about the limitations of our implementation. In particular, the use of Javascript Number type basically means we're limited to ~53-bits of integer. There are probably other limitations worth noting around things like Decimal as well.

Error: Hour 0 must be between 1 and 23 inclusive

I have the following Ion structure which was properly created in Java:

'[email protected]'::{
  start_date:2017-05-01T00:00:00.000Z,
  end_date:2017-06-01T00:00:00.000Z
}

When reading this data, ion-js fails with the following error message.

Error: Hour 0 must be between 1 and 23 inclusive
    at Timestamp.checkValid (/ion-js/dist/commonjs/es6/IonTimestamp.js:242:27)
    at new Timestamp (/ion-js/dist/commonjs/es6/IonTimestamp.js:220:14)
    at read_timestamp_value (/ion-js/dist/commonjs/es6/IonParserBinaryRaw.js:358:9)
    at ParserBinaryRaw.load_value (/ion-js/dist/commonjs/es6/IonParserBinaryRaw.js:573:21)
    at ParserBinaryRaw.timestampValue (/ion-js/dist/commonjs/es6/IonParserBinaryRaw.js:756:15)
    at BinaryReader.timestampValue (/ion-js/dist/commonjs/es6/IonBinaryReader.js:168:29)

Timestamp seems to incorrectly interprete the timezone

  • The record has a timestamp field startDate = 1498415400000.
  • This is GMT: Sunday, June 25, 2017 6:30:00 PM.
  • When creating an ion struct in Java, a corresponding field was added that reflects the timezone like start_date:2017-06-26T00:00:00.000+05:30
  1. The problem is that when reading this value with ion-js, the stringValue() produces an incorrect mixed date value 2017-06-25T18:30:0.0+05:30 which is neither the UTC nor the locatime.
  2. Also notice how seconds are formatted. They should be 00.000 instead of 0.0.

Eliminate Span exposure

The current API for readers involves making a span and then passing it into a method to make the actual reader ( makeReader(makeSpan("{foo:bar")) ). This unnecessarily exposes internal details (although, I can imagine custom implementations of the Span interface that go beyond the basic number[] and String types) and overcomplicates the API. makeReader's first parameter should be String | number[] | Span and delegate to makeSpan accordingly such that callers need only do makeReader("{foo:bar}")

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.