Skip to content
Christopher Hunt edited this page Dec 11, 2016 · 4 revisions

Validation is necessary to ensure that we don't import something unexpected. Because we can know immediately (via user feedback) that the rejected replay is bad in some way, it saves time troubleshooting later. This also guards against changes made to the format of the events being recorded from TagPro.

Validation takes place in two parts: schema validation and semantic validation. Schema validation uses JSON schema-based schemas defining the replay JSON structure (along with a validation library) and handles:

  1. Validating the structure (objects have expected properties, types of the different nodes, integers, null values, arrays where we expect)
  2. Some value validation (based on enums or patterns)

The schemas defining the version 1 format of the replay files can be seen here. The Space Telescope Science Institute has a JSON schema tutorial here that can serve as a great introduction.

Semantic validation is just whatever validation is applied that isn't covered by the above. Usually related to correlating different parts of the replay data structure, for example:

  1. At least one player exists
  2. Any complex pattern matching or conditioning (on v1 replays, at least one player must have me == "me")

Initially JSON-schema-based validation was done using is-my-json-valid (implementation can be seen on the dev branch), but since then ajv has supplanted it as the fastest. The implementation for v1.3.10 uses that.

JSON schema validation in chrome packaged app

We have two options for using ajv in the privileged background page of the extension:

  1. Compile as part of a build step using ajv-pack and then require the JS modules directly (increases the size of the compiled background page) or move the compiled modules to the extension directory and load dynamically at runtime
  2. Move ajv to a sandboxed iframe and communicate with it

The first option is simpler but blocked by an issue in ajv-pack here. I have an initial implementation of this solution on this branch.

The second option is what is implemented and has three parts:

  1. AjvProxy - ajv access point for any application code, delegates to either a sandboxed instance of ajv or an instance in the scope of the module (for permissive contexts, e.g. during testing)
  2. Sandboxed ajv - consists of the top-level script (ajv-sandboxed.js) which gets browserified and loaded via ajv-sandbox.html in an iframe. This is possible because the html file is added to the extension manifest.
  3. Sandboxed messaging - interface that uses MessageChannel to establish two-way communication between the iframe and the parent page.

That's it. validator.js loads up AjvProxy and uses it as Ajv. Limitations:

  1. If more functionality is needed from Ajv then it will need to be added to the AjvProxy.
  2. The current messaging setup also does not support passing callbacks as arguments (not limiting in the current case)
  3. The validation is necessarily async. This will likely have implications when being used for indexedDB transactions.
  4. Message-passing has an overhead when we're copying objects/strings around, but we're nowhere near the point where we need to make things more complicated for performance.

Clone this wiki locally