GithubHelp home page GithubHelp logo

ljharb / safe-array-concat Goto Github PK

View Code? Open in Web Editor NEW
5.0 2.0 1.0 56 KB

`Array.prototype.concat`, but made safe by ignoring Symbol.isConcatSpreadable

License: MIT License

JavaScript 100.00%
array concat isconcatspreadable

safe-array-concat's Introduction

safe-array-concat Version Badge

github actions coverage License Downloads

npm badge

Array.prototype.concat, but made safe by ignoring Symbol.isConcatSpreadable

Getting started

npm install --save safe-array-concat

Usage/Examples

var safeConcat = require('safe-array-concat');
var assert = require('assert');

assert.deepEqual([].concat([1, 2], 3, [[4]]), [1, 2, 3, [4]], 'arrays spread as expected with normal concat');
assert.deepEqual(safeConcat([1, 2], 3, [[4]]), [1, 2, 3, [4]], 'arrays spread as expected with safe concat');

String.prototype[Symbol.isConcatSpreadable] = true;
assert.deepEqual([].concat('foo', Object('bar')), ['foo', 'b', 'a', 'r'], 'spreadable String objects are spread with normal concat!!!');
assert.deepEqual(safeConcat('foo', Object('bar')), ['foo', Object('bar')], 'spreadable String objects are not spread with safe concat');

Array.prototype[Symbol.isConcatSpreadable] = false;
assert.deepEqual([].concat([1, 2], 3, [[4]]), [[], [1, 2], 3, [[4]]], 'non-concat-spreadable arrays do not spread with normal concat!!!');
assert.deepEqual(safeConcat([1, 2], 3, [[4]]), [1, 2, 3, [4]], 'non-concat-spreadable arrays still spread with safe concat');

Tests

Simply clone the repo, npm install, and run npm test

safe-array-concat's People

Contributors

infinity-naveen avatar ljharb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

infinity-naveen

safe-array-concat's Issues

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Warning

These dependencies are deprecated:

Datasource Name Replacement PR?
npm @types/mock-property Unavailable
npm aud Unavailable

Pending Approval

These branches will be created by Renovate only once you click their checkbox below.

  • [Deps] Update Update eslint to v8.57.0
  • [Deps] Update Update aud to v3
  • [Deps] Update Update eslint to v9
  • [Deps] Update Update nyc to v17
  • ๐Ÿ” Create all pending approval PRs at once ๐Ÿ”

Detected dependencies

github-actions
.github/workflows/node-aught.yml
.github/workflows/node-pretest.yml
.github/workflows/node-tens.yml
.github/workflows/rebase.yml
.github/workflows/require-allow-edits.yml
npm
package.json
  • call-bind ^1.0.7
  • get-intrinsic ^1.2.4
  • has-symbols ^1.0.3
  • isarray ^2.0.5
  • @arethetypeswrong/cli ^0.15.1
  • @ljharb/eslint-config ^21.1.0
  • @ljharb/tsconfig ^0.2.0
  • @types/call-bind ^1.0.5
  • @types/get-intrinsic ^1.2.2
  • @types/has-symbols ^1.0.2
  • @types/isarray ^2.0.2
  • @types/mock-property ^1.0.2
  • @types/tape ^5.6.4
  • aud ^2.0.4
  • auto-changelog ^2.4.0
  • eslint =8.8.0
  • evalmd ^0.0.19
  • in-publish ^2.0.1
  • mock-property ^1.0.3
  • npmignore ^0.3.1
  • nyc ^10.3.2
  • safe-publish-latest ^2.0.0
  • set-function-length ^1.2.2
  • tape ^5.7.5
  • node >=0.4

  • Check this box to trigger a request for Renovate to run again on this repository

Performance issue due to Symbol.isConcatSpreadable set

Description

We have been facing high CPU utilisation issues in our projects since April 2023. On debugging, we found that many dependencies were updated at that time (e.g. util.promisify, promise.prototype.finally, object.getownpropertydescriptors, etc.). And all of these started using safe-array-concat package. On further deep-driving, we observed that loading of this package safe-array-concat is impacting performance of Array concat function by around 20x in our whole application, and since concat() operation is used at lot of places in our code, it caused significant increase on our server's CPU utilisation.

Root Cause

On analysing safe-array-concat source code, we found culprit line of code:
https://github.com/ljharb/safe-array-concat/blob/f929a1b65eb3525d93296ecc12f709b18089081c/index.js#L16C1-L17C1

empty[isConcatSpreadable] = true;

Actually, this code is also not the root cause, here Symbol.isConcatSpreadable is used as per requirement. Actual root cause is the V8 Engine (which is powering NodeJs). As per it's current implementation, if we set Symbol.IsConcatSpreadable to any array or object (even such single usage will trigger it), it will make all subsequent usages of Array.concat() slower in whole application.

Reference: https://github.com/v8/v8/blob/bf4b542a1b31bbe8106e394b1dbeff02571dff4b/src/builtins/builtins-array.cc#L1542

Additional Context

In our case in all projects, the only such usage of symbol (where we are setting it to any value/array) is in this package code. As soon as we require safe-array-concat in our app, above mentioned line is executed & all subsequent concat() operations' performance is impacted.

Steps to Reproduce Issue

Code:

const loadPackage = process.env.loadPackage==="true" || false;
const count = process.env.count || 100;

if (loadPackage) {
    require('safe-array-concat');
}

const runScript = () => {
    console.log(`Running test`);

    // creating sample array of 50k size with dummy data
    const sampleArray = [];
    const arraySize = 1000*50;
    for (let i = 0; i<arraySize; i++) sampleArray.push(i);

    // Actual test:
    console.time("concatOperation");
    for (let i =0; i<count; i++) {
        sampleArray.concat(sampleArray); // <--- Testing impact on this operation's performance
    }
    console.timeEnd("concatOperation");
}

runScript();

Execution results:
loadPackage=true count=200 node safe-test.js :: 2.5 sec
loadPackage=false count=200 node safe-test.js :: 113 ms
loadPackage=true count=500 node safe-test.js :: 6.3 sec
loadPackage=false count=500 node safe-test.js :: 275 ms

Que tal adicionar um .npmignore para ignorar alguns arquivos da biblioteca?

Hello,

I would like to propose adding a .npmignore file to the project. This would allow publishing to npm to ignore files that are not essential for deployment to production environments, such as:

test/
.github/
.eslintrc
.nycrc

These files are generally only used during development and are not needed in the final distribution of the library. Implementing this change would help reduce the library package size, thus optimizing efficiency for end users.

I include a screenshot below to illustrate the location of the files mentioned in the current repository:

Captura de tela de 2023-11-28 08-27-23

Thank you for your attention and I am available to discuss this suggestion further.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.