-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Vendor+IE8-ify json-stringify-safe, fix handler with XDomainRequest #883
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
399171c
Add vendored json-stringify-safe
LewisJEllis bfa1626
Make json-stringify-safe IE8 compatible
LewisJEllis 0626180
Add captureMessage/captureException to scratch example
LewisJEllis e19a1b2
Use vendored json-stringify-safe in raven.js
LewisJEllis b7ce7e0
Make request handler work properly with XDomainRequest
LewisJEllis 8df1963
Add vendored json-stringify-safe tests
LewisJEllis d911cb7
Make vendored json-stringify-safe tests use assert instead of must
LewisJEllis File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
/*global Mocha, assert*/ | ||
var Sinon = require("sinon") | ||
var stringify = require('../../vendor/json-stringify-safe/stringify'); | ||
|
||
function jsonify(obj) { return JSON.stringify(obj, null, 2) } | ||
|
||
describe("Stringify", function() { | ||
it("must stringify circular objects", function() { | ||
var obj = {name: "Alice"} | ||
obj.self = obj | ||
var json = stringify(obj, null, 2) | ||
assert.deepEqual(json, jsonify({name: "Alice", self: "[Circular ~]"})) | ||
}) | ||
|
||
it("must stringify circular objects with intermediaries", function() { | ||
var obj = {name: "Alice"} | ||
obj.identity = {self: obj} | ||
var json = stringify(obj, null, 2) | ||
assert.deepEqual(json, jsonify({name: "Alice", identity: {self: "[Circular ~]"}})) | ||
}) | ||
|
||
it("must stringify circular objects deeper", function() { | ||
var obj = {name: "Alice", child: {name: "Bob"}} | ||
obj.child.self = obj.child | ||
|
||
assert.deepEqual(stringify(obj, null, 2), jsonify({ | ||
name: "Alice", | ||
child: {name: "Bob", self: "[Circular ~.child]"} | ||
})) | ||
}) | ||
|
||
it("must stringify circular objects deeper with intermediaries", function() { | ||
var obj = {name: "Alice", child: {name: "Bob"}} | ||
obj.child.identity = {self: obj.child} | ||
|
||
assert.deepEqual(stringify(obj, null, 2), jsonify({ | ||
name: "Alice", | ||
child: {name: "Bob", identity: {self: "[Circular ~.child]"}} | ||
})) | ||
}) | ||
|
||
it("must stringify circular objects in an array", function() { | ||
var obj = {name: "Alice"} | ||
obj.self = [obj, obj] | ||
|
||
assert.deepEqual(stringify(obj, null, 2), jsonify({ | ||
name: "Alice", self: ["[Circular ~]", "[Circular ~]"] | ||
})) | ||
}) | ||
|
||
it("must stringify circular objects deeper in an array", function() { | ||
var obj = {name: "Alice", children: [{name: "Bob"}, {name: "Eve"}]} | ||
obj.children[0].self = obj.children[0] | ||
obj.children[1].self = obj.children[1] | ||
|
||
assert.deepEqual(stringify(obj, null, 2), jsonify({ | ||
name: "Alice", | ||
children: [ | ||
{name: "Bob", self: "[Circular ~.children.0]"}, | ||
{name: "Eve", self: "[Circular ~.children.1]"} | ||
] | ||
})) | ||
}) | ||
|
||
it("must stringify circular arrays", function() { | ||
var obj = [] | ||
obj.push(obj) | ||
obj.push(obj) | ||
var json = stringify(obj, null, 2) | ||
assert.deepEqual(json, jsonify(["[Circular ~]", "[Circular ~]"])) | ||
}) | ||
|
||
it("must stringify circular arrays with intermediaries", function() { | ||
var obj = [] | ||
obj.push({name: "Alice", self: obj}) | ||
obj.push({name: "Bob", self: obj}) | ||
|
||
assert.deepEqual(stringify(obj, null, 2), jsonify([ | ||
{name: "Alice", self: "[Circular ~]"}, | ||
{name: "Bob", self: "[Circular ~]"} | ||
])) | ||
}) | ||
|
||
it("must stringify repeated objects in objects", function() { | ||
var obj = {} | ||
var alice = {name: "Alice"} | ||
obj.alice1 = alice | ||
obj.alice2 = alice | ||
|
||
assert.deepEqual(stringify(obj, null, 2), jsonify({ | ||
alice1: {name: "Alice"}, | ||
alice2: {name: "Alice"} | ||
})) | ||
}) | ||
|
||
it("must stringify repeated objects in arrays", function() { | ||
var alice = {name: "Alice"} | ||
var obj = [alice, alice] | ||
var json = stringify(obj, null, 2) | ||
assert.deepEqual(json, jsonify([{name: "Alice"}, {name: "Alice"}])) | ||
}) | ||
|
||
it("must call given decycler and use its output", function() { | ||
var obj = {} | ||
obj.a = obj | ||
obj.b = obj | ||
|
||
var decycle = Sinon.spy(function() { return decycle.callCount }) | ||
var json = stringify(obj, null, 2, decycle) | ||
assert.deepEqual(json, jsonify({a: 1, b: 2}, null, 2)) | ||
|
||
assert.strictEqual(decycle.callCount, 2) | ||
assert.strictEqual(decycle.thisValues[0], obj) | ||
assert.strictEqual(decycle.args[0][0], "a") | ||
assert.strictEqual(decycle.args[0][1], obj) | ||
assert.strictEqual(decycle.thisValues[1], obj) | ||
assert.strictEqual(decycle.args[1][0], "b") | ||
assert.strictEqual(decycle.args[1][1], obj) | ||
}) | ||
|
||
it("must call replacer and use its output", function() { | ||
var obj = {name: "Alice", child: {name: "Bob"}} | ||
|
||
var replacer = Sinon.spy(bangString) | ||
var json = stringify(obj, replacer, 2) | ||
assert.deepEqual(json, jsonify({name: "Alice!", child: {name: "Bob!"}})) | ||
|
||
assert.strictEqual(replacer.callCount, 4) | ||
assert.strictEqual(replacer.args[0][0], "") | ||
assert.strictEqual(replacer.args[0][1], obj) | ||
assert.strictEqual(replacer.thisValues[1], obj) | ||
assert.strictEqual(replacer.args[1][0], "name") | ||
assert.strictEqual(replacer.args[1][1], "Alice") | ||
assert.strictEqual(replacer.thisValues[2], obj) | ||
assert.strictEqual(replacer.args[2][0], "child") | ||
assert.strictEqual(replacer.args[2][1], obj.child) | ||
assert.strictEqual(replacer.thisValues[3], obj.child) | ||
assert.strictEqual(replacer.args[3][0], "name") | ||
assert.strictEqual(replacer.args[3][1], "Bob") | ||
}) | ||
|
||
it("must call replacer after describing circular references", function() { | ||
var obj = {name: "Alice"} | ||
obj.self = obj | ||
|
||
var replacer = Sinon.spy(bangString) | ||
var json = stringify(obj, replacer, 2) | ||
assert.deepEqual(json, jsonify({name: "Alice!", self: "[Circular ~]!"})) | ||
|
||
assert.strictEqual(replacer.callCount, 3) | ||
assert.strictEqual(replacer.args[0][0], "") | ||
assert.strictEqual(replacer.args[0][1], obj) | ||
assert.strictEqual(replacer.thisValues[1], obj) | ||
assert.strictEqual(replacer.args[1][0], "name") | ||
assert.strictEqual(replacer.args[1][1], "Alice") | ||
assert.strictEqual(replacer.thisValues[2], obj) | ||
assert.strictEqual(replacer.args[2][0], "self") | ||
assert.strictEqual(replacer.args[2][1], "[Circular ~]") | ||
}) | ||
|
||
it("must call given decycler and use its output for nested objects", | ||
function() { | ||
var obj = {} | ||
obj.a = obj | ||
obj.b = {self: obj} | ||
|
||
var decycle = Sinon.spy(function() { return decycle.callCount }) | ||
var json = stringify(obj, null, 2, decycle) | ||
assert.deepEqual(json, jsonify({a: 1, b: {self: 2}})) | ||
|
||
assert.strictEqual(decycle.callCount, 2) | ||
assert.strictEqual(decycle.args[0][0], "a") | ||
assert.strictEqual(decycle.args[0][1], obj) | ||
assert.strictEqual(decycle.args[1][0], "self") | ||
assert.strictEqual(decycle.args[1][1], obj) | ||
}) | ||
|
||
it("must use decycler's output when it returned null", function() { | ||
var obj = {a: "b"} | ||
obj.self = obj | ||
obj.selves = [obj, obj] | ||
|
||
function decycle() { return null } | ||
assert.deepEqual(stringify(obj, null, 2, decycle), jsonify({ | ||
a: "b", | ||
self: null, | ||
selves: [null, null] | ||
})) | ||
}) | ||
|
||
it("must use decycler's output when it returned undefined", function() { | ||
var obj = {a: "b"} | ||
obj.self = obj | ||
obj.selves = [obj, obj] | ||
|
||
function decycle() {} | ||
assert.deepEqual(stringify(obj, null, 2, decycle), jsonify({ | ||
a: "b", | ||
selves: [null, null] | ||
})) | ||
}) | ||
|
||
it("must throw given a decycler that returns a cycle", function() { | ||
var obj = {} | ||
obj.self = obj | ||
var err | ||
function identity(key, value) { return value } | ||
try { stringify(obj, null, 2, identity) } catch (ex) { err = ex } | ||
assert.ok(err instanceof TypeError) | ||
}) | ||
|
||
describe(".getSerialize", function() { | ||
it("must stringify circular objects", function() { | ||
var obj = {a: "b"} | ||
obj.circularRef = obj | ||
obj.list = [obj, obj] | ||
|
||
var json = JSON.stringify(obj, stringify.getSerialize(), 2) | ||
assert.deepEqual(json, jsonify({ | ||
"a": "b", | ||
"circularRef": "[Circular ~]", | ||
"list": ["[Circular ~]", "[Circular ~]"] | ||
})) | ||
}) | ||
|
||
// This is the behavior as of Mar 3, 2015. | ||
// The serializer function keeps state inside the returned function and | ||
// so far I'm not sure how to not do that. JSON.stringify's replacer is not | ||
// called _after_ serialization. | ||
xit("must return a function that could be called twice", function() { | ||
var obj = {name: "Alice"} | ||
obj.self = obj | ||
|
||
var json | ||
var serializer = stringify.getSerialize() | ||
|
||
json = JSON.stringify(obj, serializer, 2) | ||
assert.deepEqual(json, jsonify({name: "Alice", self: "[Circular ~]"})) | ||
|
||
json = JSON.stringify(obj, serializer, 2) | ||
assert.deepEqual(json, jsonify({name: "Alice", self: "[Circular ~]"})) | ||
}) | ||
}) | ||
}) | ||
|
||
function bangString(key, value) { | ||
return typeof value == "string" ? value + "!" : value | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
'use strict'; | ||
|
||
/* | ||
json-stringify-safe | ||
Like JSON.stringify, but doesn't throw on circular references. | ||
|
||
Originally forked from https://github.com/isaacs/json-stringify-safe | ||
version 5.0.1 on 3/8/2017 and modified for IE8 compatibility. | ||
Tests for this are in test/vendor. | ||
|
||
ISC license: https://github.com/isaacs/json-stringify-safe/blob/master/LICENSE | ||
*/ | ||
|
||
exports = module.exports = stringify | ||
exports.getSerialize = serializer | ||
|
||
function indexOf(haystack, needle) { | ||
for (var i = 0; i < haystack.length; ++i) { | ||
if (haystack[i] === needle) return i; | ||
} | ||
return -1; | ||
} | ||
|
||
function stringify(obj, replacer, spaces, cycleReplacer) { | ||
return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces) | ||
} | ||
|
||
function serializer(replacer, cycleReplacer) { | ||
var stack = [], keys = [] | ||
|
||
if (cycleReplacer == null) cycleReplacer = function(key, value) { | ||
if (stack[0] === value) return '[Circular ~]' | ||
return '[Circular ~.' + keys.slice(0, indexOf(stack, value)).join('.') + ']' | ||
} | ||
|
||
return function(key, value) { | ||
if (stack.length > 0) { | ||
var thisPos = indexOf(stack, this); | ||
~thisPos ? stack.splice(thisPos + 1) : stack.push(this) | ||
~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key) | ||
if (~indexOf(stack, value)) value = cycleReplacer.call(this, key, value) | ||
} | ||
else stack.push(value) | ||
|
||
return replacer == null ? value : replacer.call(this, key, value) | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I quickly experimented w/ having a helper
onerror
function that could be called from either theXDomainRequest
handler oronreadystatechange
, but it quickly ended up taking up more code so nm ...