From 626dfde31f4603f606c43762f8c1cfe5fac3ad98 Mon Sep 17 00:00:00 2001 From: Colin Casey Date: Mon, 22 Nov 2021 23:45:10 -0400 Subject: [PATCH] Support for React Native This PR fixes #222 by: - introducing a fallback for the `util.*` code paths used as indicated in [this comment](/~https://github.com/salesforce/tough-cookie/issues/222#issue-1033380775) - adding a dependency on `url-parse` to act as a polyfill for the usage of `require('url').parse` --- lib/cookie.js | 13 ++++---- lib/memstore.js | 4 ++- lib/node-util.js | 20 ++++++++++++ package.json | 3 +- test/jsc_compatibility_test.js | 58 ++++++++++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 lib/node-util.js create mode 100644 test/jsc_compatibility_test.js diff --git a/lib/cookie.js b/lib/cookie.js index 559546b0..94876910 100644 --- a/lib/cookie.js +++ b/lib/cookie.js @@ -30,8 +30,8 @@ */ "use strict"; const punycode = require("punycode"); -const urlParse = require("url").parse; -const util = require("util"); +const urlParse = require("url-parse"); +const nodeUtil = require("./node-util"); const pubsuffix = require("./pubsuffix-psl"); const Store = require("./store").Store; const MemoryCookieStore = require("./memstore").MemoryCookieStore; @@ -810,6 +810,7 @@ const cookieDefaults = { class Cookie { constructor(options = {}) { + const util = nodeUtil(); if (util.inspect.custom) { this[util.inspect.custom] = this.inspect; } @@ -1110,7 +1111,7 @@ class CookieJar { } setCookie(cookie, url, options, cb) { - validators.validate(validators.isNonEmptyString(url), cb, options); + validators.validate(validators.isNonEmptyString(url), cb, options); let err; if (validators.isFunction(url)) { @@ -1646,7 +1647,7 @@ class CookieJar { serialized = strOrObj; } - const jar = new CookieJar(store, { + const jar = new CookieJar(store, { rejectPublicSuffixes: serialized.rejectPublicSuffixes, looseMode: serialized.enableLooseMode, allowSpecialUseDomain: serialized.allowSpecialUseDomain, @@ -1663,9 +1664,9 @@ class CookieJar { static deserializeSync(strOrObj, store) { const serialized = typeof strOrObj === "string" ? JSON.parse(strOrObj) : strOrObj; - const jar = new CookieJar(store, { + const jar = new CookieJar(store, { rejectPublicSuffixes: serialized.rejectPublicSuffixes, - looseMode: serialized.enableLooseMode + looseMode: serialized.enableLooseMode }); // catch this mistake early: diff --git a/lib/memstore.js b/lib/memstore.js index 912eead3..051e1ff8 100644 --- a/lib/memstore.js +++ b/lib/memstore.js @@ -33,19 +33,21 @@ const { fromCallback } = require("universalify"); const Store = require("./store").Store; const permuteDomain = require("./permuteDomain").permuteDomain; const pathMatch = require("./pathMatch").pathMatch; -const util = require("util"); +const nodeUtil = require("./node-util"); class MemoryCookieStore extends Store { constructor() { super(); this.synchronous = true; this.idx = {}; + const util = nodeUtil(); if (util.inspect.custom) { this[util.inspect.custom] = this.inspect; } } inspect() { + const util = nodeUtil(); return `{ idx: ${util.inspect(this.idx, false, 2)} }`; } diff --git a/lib/node-util.js b/lib/node-util.js new file mode 100644 index 00000000..16e7743d --- /dev/null +++ b/lib/node-util.js @@ -0,0 +1,20 @@ +// a stand-in for util that does nothing but prevent the existing +// node:util code paths from exploding +function nullUtilInspect() { + return ""; +} +nullUtilInspect.custom = Symbol.for("nodejs.util.inspect.custom"); +const nullUtil = { inspect: nullUtilInspect }; + +module.exports = function nodeUtil() { + try { + const jscCompatibility = + process && process.env && process.env.JSC_COMPATIBILITY === "enabled"; + if (!jscCompatibility) { + return require("util"); + } + } catch (e) { + // ignore + } + return nullUtil; +}; diff --git a/package.json b/package.json index e07dcb7c..3006a819 100644 --- a/package.json +++ b/package.json @@ -104,6 +104,7 @@ "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", - "universalify": "^0.1.2" + "universalify": "^0.1.2", + "url-parse": "^1.5.3" } } diff --git a/test/jsc_compatibility_test.js b/test/jsc_compatibility_test.js new file mode 100644 index 00000000..663bee7b --- /dev/null +++ b/test/jsc_compatibility_test.js @@ -0,0 +1,58 @@ +/*! + * Copyright (c) 2015, Salesforce.com, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Salesforce.com nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +"use strict"; +const vows = require("vows"); +const assert = require("assert"); +const tough = require("../lib/cookie"); +const util = require("util"); +const nodeUtil = require("../lib/node-util"); +const Cookie = tough.Cookie; + +vows + .describe("JavaScriptCore Compatibility") + .addBatch({ + util: { + topic: function() { + process.env.JSC_COMPATIBILITY = "enabled"; + return new Cookie(); + }, + "should not error out on util.* code paths": function(c) { + const nullUtil = nodeUtil(); + assert.equal(nullUtil.inspect(c), ""); + assert.equal(nullUtil.inspect.custom, util.inspect.custom); + }, + teardown: function() { + delete process.env.JSC_COMPATIBILITY; + } + } + }) + .export(module);