stripe-node icon indicating copy to clipboard operation
stripe-node copied to clipboard

`_prepResources()` and `ResourceNamespace` iterate all properties, but don't check `hasOwnProperty`

Open seanadkinson opened this issue 1 year ago • 0 comments
trafficstars

Describe the bug

Hi there, when including the scope-extensions-js package in my project, Stripe errors out with the following on startup:

<project>/node_modules/scope-extensions-js/dist/index.js:2
    return block(this);
           ^
TypeError: block is not a function
    at new Object.let (<project>/node_modules/scope-extensions-js/dist/index.js:2:12)
    at new ResourceNamespace (<project>/node_modules/stripe/cjs/ResourceNamespace.js:9:26)
    at new <anonymous> (<project>/node_modules/stripe/cjs/ResourceNamespace.js:15:16)
    at Stripe._prepResources (<project>/node_modules/stripe/cjs/stripe.core.js:321:65)
    at new Stripe (<project>/node_modules/stripe/cjs/stripe.core.js:99:14)
    at Object.<anonymous> (<project>/src/services/stripeService.ts:17:16)
    at Module._compile (node:internal/modules/cjs/loader:1369:14)
    at Module.m._compile (<project>/node_modules/ts-node/src/index.ts:1618:23)
    at Module._extensions..js (node:internal/modules/cjs/loader:1427:10)
    at Object.require.extensions.<computed> [as .ts] (<project>/node_modules/ts-node/src/index.ts:1621:12)

This is a ts-node project, but not sure if that's important.

The issues appears to be these couple loops, which iterate resources, but pick up unexpected things on the prototype chain:

// stripe.core.js, line 318
        _prepResources() {
            for (const name in resources) {
                if (resources.hasOwnProperty(name)) {
                    // @ts-ignore
                    this[(0, utils_js_1.pascalToCamelCase)(name)] = new resources[name](this);
                }
            }
        },


// ResourceNamescape.js, line 6
function ResourceNamespace(stripe, resources) {
    for (const name in resources) {
        const camelCaseName = name[0].toLowerCase() + name.substring(1);
        const resource = new resources[name](stripe);
        this[camelCaseName] = resource;
    }
}

I believe that we want an Object.hasOwnProperty() check inside those loops, to avoid this issue.

Here is a patch file (using patch-package) that fixes the issue for me:

diff --git a/node_modules/stripe/cjs/ResourceNamespace.js b/node_modules/stripe/cjs/ResourceNamespace.js
index 25c6cf3..20d2431 100644
--- a/node_modules/stripe/cjs/ResourceNamespace.js
+++ b/node_modules/stripe/cjs/ResourceNamespace.js
@@ -5,9 +5,11 @@ exports.resourceNamespace = void 0;
 // It also works recursively, so you could do i.e. `stripe.billing.invoicing.pay`.
 function ResourceNamespace(stripe, resources) {
     for (const name in resources) {
-        const camelCaseName = name[0].toLowerCase() + name.substring(1);
-        const resource = new resources[name](stripe);
-        this[camelCaseName] = resource;
+        if (resources.hasOwnProperty(name)) {
+            const camelCaseName = name[0].toLowerCase() + name.substring(1);
+            const resource = new resources[name](stripe);
+            this[camelCaseName] = resource;
+        }
     }
 }
 function resourceNamespace(namespace, resources) {
diff --git a/node_modules/stripe/cjs/stripe.core.js b/node_modules/stripe/cjs/stripe.core.js
index 4baa951..aff9860 100644
--- a/node_modules/stripe/cjs/stripe.core.js
+++ b/node_modules/stripe/cjs/stripe.core.js
@@ -317,8 +317,10 @@ function createStripe(platformFunctions, requestSender = defaultRequestSenderFac
          */
         _prepResources() {
             for (const name in resources) {
-                // @ts-ignore
-                this[(0, utils_js_1.pascalToCamelCase)(name)] = new resources[name](this);
+                if (resources.hasOwnProperty(name)) {
+                    // @ts-ignore
+                    this[(0, utils_js_1.pascalToCamelCase)(name)] = new resources[name](this);
+                }
             }
         },
         /**

To Reproduce

Use the following package.json:

{
  "name": "test",
  "version": "1.0.0",
  "main": "index.ts",
  "scripts": {
    "start": "ts-node ./index.ts"
  },
  "dependencies": {
    "scope-extensions-js": "^1.1.0",
    "stripe": "^15.12.0",
    "ts-node": "^10.9.2",
    "typescript": "^5.5.2"
  }
}

And index.ts:

import 'scope-extensions-js';
import Stripe from 'stripe';

const stripe = new Stripe('abc123', {
    apiVersion: '2024-04-10',
    typescript: true,
});

console.log('Done!');

Run yarn && yarn start (or the npm equivalent). See error.

❯ yarn start                                                                                                                                                                                        11:27:51 AM, Jun 21
yarn run v1.22.22
$ ts-node ./index.ts
<project>/node_modules/scope-extensions-js/dist/index.js:2
    return block(this);
           ^
TypeError: block is not a function
    at new Object.let (<project>/node_modules/scope-extensions-js/dist/index.js:2:12)
    at new ResourceNamespace (<project>/node_modules/stripe/cjs/ResourceNamespace.js:9:26)
    at new <anonymous> (<project>/node_modules/stripe/cjs/ResourceNamespace.js:15:16)
    at Stripe._prepResources (<project>/node_modules/stripe/cjs/stripe.core.js:321:65)
    at new Stripe (<project>/node_modules/stripe/cjs/stripe.core.js:99:14)
    at Object.<anonymous> (/<project>/index.ts:4:16)
    at Module._compile (node:internal/modules/cjs/loader:1369:14)
    at Module.m._compile (<project>/node_modules/ts-node/src/index.ts:1618:23)
    at Module._extensions..js (node:internal/modules/cjs/loader:1427:10)
    at Object.require.extensions.<computed> [as .ts] (<project>/node_modules/ts-node/src/index.ts:1621:12)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Expected behavior

Project should startup without error.

Code snippets

No response

OS

MacOS Sonoma 14.5

Node version

v20.12.1

Library version

v15.12.0

API version

2024-04-10

Additional context

No response

seanadkinson avatar Jun 21 '24 18:06 seanadkinson