├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── FUNDING.yml └── ISSUE_TEMPLATE.md ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── .travis.yml ├── LICENSE ├── README.md ├── __tests__ ├── .eslintrc.json ├── ArraySeq.ts ├── Conversion.ts ├── Equality.ts ├── IndexedSeq.ts ├── KeyedSeq.ts ├── List.ts ├── ListJS.js ├── Map.ts ├── MultiRequire.js ├── ObjectSeq.ts ├── OrderedMap.ts ├── OrderedSet.ts ├── Predicates.ts ├── Range.ts ├── Record.ts ├── RecordJS.js ├── Repeat.ts ├── Seq.ts ├── Set.ts ├── Stack.ts ├── __snapshots__ │ └── Record.ts.snap ├── concat.ts ├── count.ts ├── find.ts ├── flatten.ts ├── fromJS.ts ├── get.ts ├── getIn.ts ├── groupBy.ts ├── hasIn.ts ├── hash.ts ├── interpose.ts ├── issues.ts ├── join.ts ├── merge.ts ├── minmax.ts ├── slice.ts ├── sort.ts ├── splice.ts ├── transformerProtocol.ts ├── updateIn.ts ├── utils.js └── zip.ts ├── package.json ├── pages ├── .babelrc.json ├── .eslintrc.json ├── lib │ ├── .eslintrc.json │ ├── TypeKind.js │ ├── collectMemberGroups.js │ ├── genMarkdownDoc.js │ ├── genTypeDefData.js │ ├── getTypeDefs.js │ ├── markdown.js │ ├── markdownDocs.js │ ├── prism.js │ └── runkit-embed.js └── src │ ├── docs │ ├── index.html │ ├── src │ │ ├── Defs.js │ │ ├── DocHeader.js │ │ ├── DocOverview.js │ │ ├── DocSearch.js │ │ ├── MarkDown.js │ │ ├── SideBar.js │ │ ├── TypeDocumentation.js │ │ ├── bundle.js │ │ ├── components │ │ │ ├── Disclaimer.js │ │ │ ├── FunctionDoc.js │ │ │ ├── MemberDoc.js │ │ │ └── TypeDoc.js │ │ ├── constants.js │ │ ├── global.js │ │ ├── index.js │ │ ├── isMobile.js │ │ ├── server.js │ │ └── style.less │ └── version.html │ ├── index.html │ ├── src │ ├── Header.js │ ├── Logo.js │ ├── SVGSet.js │ ├── StarBtn.js │ ├── StarBtn.less │ ├── base.less │ ├── bundle.js │ ├── global.js │ ├── index.js │ ├── loadJSON.js │ ├── server.js │ └── style.less │ └── static │ └── favicon.png ├── perf ├── List.js ├── Map.js ├── Record.js └── toJS.js ├── resources ├── COPYRIGHT ├── bench.js ├── copy-dist-typedefs.js ├── deploy-ghpages.sh ├── dist-stats.js ├── gitpublish.sh ├── gulpfile.js ├── identity.ai ├── identity.svg ├── immutable-global.js ├── jest.d.ts ├── jestPreprocessor.js ├── jestResolver.js ├── react-global.js ├── rollup-config-es.js └── rollup-config.js ├── src ├── Collection.js ├── CollectionImpl.js ├── Hash.js ├── Immutable.js ├── Iterator.js ├── List.js ├── Map.js ├── Math.js ├── Operations.js ├── OrderedMap.js ├── OrderedSet.js ├── Range.js ├── Record.js ├── Repeat.js ├── Seq.js ├── Set.js ├── Stack.js ├── TrieUtils.js ├── fromJS.js ├── functional │ ├── get.js │ ├── getIn.js │ ├── has.js │ ├── hasIn.js │ ├── merge.js │ ├── remove.js │ ├── removeIn.js │ ├── set.js │ ├── setIn.js │ ├── update.js │ └── updateIn.js ├── is.js ├── methods │ ├── README.md │ ├── asImmutable.js │ ├── asMutable.js │ ├── deleteIn.js │ ├── getIn.js │ ├── hasIn.js │ ├── merge.js │ ├── mergeDeep.js │ ├── mergeDeepIn.js │ ├── mergeIn.js │ ├── setIn.js │ ├── toObject.js │ ├── update.js │ ├── updateIn.js │ ├── wasAltered.js │ └── withMutations.js ├── predicates │ ├── isAssociative.js │ ├── isCollection.js │ ├── isImmutable.js │ ├── isIndexed.js │ ├── isKeyed.js │ ├── isList.js │ ├── isMap.js │ ├── isOrdered.js │ ├── isOrderedMap.js │ ├── isOrderedSet.js │ ├── isRecord.js │ ├── isSeq.js │ ├── isSet.js │ ├── isStack.js │ └── isValueObject.js ├── toJS.js └── utils │ ├── arrCopy.js │ ├── assertNotInfinite.js │ ├── coerceKeyPath.js │ ├── createClass.js │ ├── deepEqual.js │ ├── hasOwnProperty.js │ ├── invariant.js │ ├── isArrayLike.js │ ├── isDataStructure.js │ ├── isPlainObj.js │ ├── mixin.js │ ├── quoteString.js │ └── shallowCopy.js ├── tslint.json ├── type-definitions ├── Immutable.d.ts ├── immutable.js.flow ├── tests │ ├── .flowconfig │ ├── covariance.js │ ├── es6-collections.js │ ├── immutable-flow.js │ ├── merge.js │ ├── predicates.js │ └── record.js ├── ts-tests │ ├── covariance.ts │ ├── es6-collections.ts │ ├── exports.ts │ ├── functional.ts │ ├── index.d.ts │ ├── list.ts │ ├── map.ts │ ├── ordered-map.ts │ ├── ordered-set.ts │ ├── range.ts │ ├── record.ts │ ├── repeat.ts │ ├── seq.ts │ ├── set.ts │ ├── stack.ts │ ├── tsconfig.json │ └── tslint.json └── tsconfig.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | 9 | [*.{js,d.ts,json,html,md,sh}] 10 | charset = utf-8 11 | indent_style = space 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /pages/out/** 2 | /pages/generated/** 3 | /dist/** 4 | node_modules 5 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parserOptions": { 4 | "ecmaVersion": 6, 5 | "sourceType": "module" 6 | }, 7 | "extends": ["airbnb", "prettier", "prettier/react"], 8 | "plugins": ["react"], 9 | "rules": { 10 | "array-callback-return": "off", 11 | "block-scoped-var": "off", 12 | "class-methods-use-this": "off", 13 | "consistent-return": "off", 14 | "constructor-super": "off", 15 | "default-case": "off", 16 | "func-names": "off", 17 | "max-classes-per-file": "off", 18 | "no-bitwise": "off", 19 | "no-cond-assign": "off", 20 | "no-constant-condition": "off", 21 | "no-continue": "off", 22 | "no-else-return": "error", 23 | "no-empty": "error", 24 | "no-lonely-if": "error", 25 | "no-multi-assign": "off", 26 | "no-nested-ternary": "off", 27 | "no-param-reassign": "off", 28 | "no-plusplus": "off", 29 | "no-prototype-builtins": "off", 30 | "no-restricted-syntax": "off", 31 | "no-return-assign": "off", 32 | "no-self-compare": "off", 33 | "no-sequences": "off", 34 | "no-shadow": "off", 35 | "no-this-before-super": "off", 36 | "no-underscore-dangle": "off", 37 | "no-unused-expressions": "off", 38 | "no-unused-vars": "error", 39 | "no-use-before-define": "off", 40 | "no-useless-concat": "error", 41 | "no-var": "error", 42 | "object-shorthand": "off", 43 | "one-var": "error", 44 | "operator-assignment": "error", 45 | "prefer-destructuring": "off", 46 | "prefer-rest-params": "off", 47 | "prefer-spread": "off", 48 | "prefer-template": "off", 49 | "spaced-comment": "off", 50 | "vars-on-top": "off", 51 | "react/destructuring-assignment": "off", 52 | "react/jsx-boolean-value": "off", 53 | "react/jsx-curly-brace-presence": "off", 54 | "react/jsx-filename-extension": "off", 55 | "react/no-array-index-key": "off", 56 | "react/no-danger": "off", 57 | "react/no-multi-comp": "off", 58 | "react/prefer-es6-class": "off", 59 | "react/prefer-stateless-function": "off", 60 | "react/prop-types": "off", 61 | "react/self-closing-comp": "error", 62 | "react/sort-comp": "off", 63 | "import/newline-after-import": "error", 64 | "import/no-cycle": "off", 65 | "import/no-extraneous-dependencies": "off", 66 | "import/no-mutable-exports": "error", 67 | "import/no-unresolved": "error", 68 | "import/no-useless-path-segments": "off", 69 | "import/order": "off", 70 | "import/prefer-default-export": "off", 71 | "jsx-a11y/no-static-element-interactions": "off" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://code.fb.com/codeofconduct/) so that you can understand what actions will and will not be tolerated. 4 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Have a question? 2 | 3 | Please ask questions on [Stack Overflow](https://stackoverflow.com/questions/tagged/immutable.js) instead of opening a Github Issue. There are more people on Stack Overflow who 4 | can answer questions, and good answers can be searchable and canonical. 5 | 6 | # Issues 7 | 8 | We use GitHub issues to track bugs. Please ensure your bug description is clear 9 | and has sufficient instructions to be able to reproduce the issue. 10 | 11 | The absolute best way to report a bug is to submit a pull request including a 12 | new failing test which describes the bug. When the bug is fixed, your pull 13 | request can then be merged! 14 | 15 | The next best way to report a bug is to provide a reduced test case on jsFiddle 16 | or jsBin or produce exact code inline in the issue which will reproduce the bug. 17 | 18 | Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe 19 | disclosure of security bugs. In those cases, please go through the process 20 | outlined on that page and do not file a public issue. 21 | 22 | # Code of Conduct 23 | 24 | The code of conduct is described in [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) 25 | 26 | # Pull Requests 27 | 28 | All active development of Immutable JS happens on GitHub. We actively welcome 29 | your [pull requests](https://help.github.com/articles/creating-a-pull-request). 30 | 31 | 1. Fork the repo and create your branch from `master`. 32 | 2. Install all dependencies. (`npm install`) 33 | 3. If you've added code, add tests. 34 | 4. If you've changed APIs, update the documentation. 35 | 5. Build generated JS, run tests and ensure your code passes lint. (`npm run test`) 36 | 6. If you haven't already, complete the Contributor License Agreement ("CLA"). 37 | 38 | ## Documentation 39 | 40 | Documentation for Immutable.js (hosted at http://facebook.github.io/immutable-js) 41 | is developed in `pages/`. Run `npm start` to get a local copy in your browser 42 | while making edits. 43 | 44 | ## Contributor License Agreement ("CLA") 45 | 46 | In order to accept your pull request, we need you to submit a CLA. You only need 47 | to do this once to work on any of Facebook's open source projects. 48 | 49 | Complete your CLA here: 50 | 51 | ## Coding Style 52 | 53 | - 2 spaces for indentation (no tabs) 54 | - 80 character line length strongly preferred. 55 | - Prefer `'` over `"` 56 | - ES6 Harmony when possible. 57 | - Use semicolons; 58 | - Trailing commas, 59 | - Avd abbr wrds. 60 | 61 | # Functionality Testing 62 | 63 | Run the following command to build the library and test functionality: 64 | 65 | ```bash 66 | npm run test 67 | ``` 68 | 69 | ## Performance Regression Testing 70 | 71 | Performance tests run against master and your feature branch. 72 | Make sure to commit your changes in your local feature branch before proceeding. 73 | 74 | These commands assume you have a remote named `upstream` amd that you do not already have a local `master` branch: 75 | 76 | ```bash 77 | git fetch upstream 78 | git checkout -b master upstream/master 79 | ``` 80 | 81 | These commands build `dist` and commit `dist/immutable.js` to `master` so that the regression tests can run. 82 | 83 | ```bash 84 | npm run test 85 | git add dist/immutable.js -f 86 | git commit -m 'perf test prerequisite.' 87 | ``` 88 | 89 | Switch back to your feature branch, and run the following command to run regression tests: 90 | 91 | ```bash 92 | npm run test 93 | npm run perf 94 | ``` 95 | 96 | Sample output: 97 | 98 | ```bash 99 | > immutable@4.0.0-rc.9 perf ~/github.com/facebook/immutable-js 100 | > node ./resources/bench.js 101 | 102 | List > builds from array of 2 103 | Old: 678,974 683,071 687,218 ops/sec 104 | New: 669,012 673,553 678,157 ops/sec 105 | compare: 1 -1 106 | diff: -1.4% 107 | rme: 0.64% 108 | ``` 109 | 110 | ## License 111 | 112 | By contributing to Immutable.js, you agree that your contributions will be 113 | licensed under its MIT license. 114 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [Methuselah96] 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 33 | 34 | ### What happened 35 | 36 | 38 | 39 | ### How to reproduce 40 | 41 | 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .*.haste_cache.* 2 | node_modules 3 | npm-debug.log 4 | yarn-error.log 5 | .DS_Store 6 | *~ 7 | *.swp 8 | .idea 9 | *.iml 10 | TODO 11 | /pages/out 12 | /pages/generated 13 | /gh-pages 14 | /npm 15 | /dist 16 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | pages/generated 3 | pages/out 4 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: lts/* 4 | 5 | cache: yarn 6 | script: 7 | - yarn format:check 8 | - yarn build 9 | - yarn lint 10 | # See https://jestjs.io/docs/en/troubleshooting.html#tests-are-extremely-slow-on-docker-andor-continuous-integration-ci-server 11 | - yarn test --maxWorkers=2 12 | - yarn type-check 13 | 14 | env: 15 | global: 16 | - secure: 'L8yOQOAjsuos8H+XhnnQ6UVUraGREwkwP84C7D5mxSRm+MhoJHhBxO0PpQhkbRfCQ4lYJfeimBouhFQ/Y07yMbU57gY5r7dI44bfWlhx6lutOH7NmPuh02EYeL2hkyyEpWFFMc+Is7bS8lvBf7r/pp5tG74xhqpv/UH8TQTWR0p57YYh3ddIuMAmSqKlrUaCYs94se3YtIIy/M7DMjQFwrxL3Kn30nLcja5Z8LEov+j4+tcoJZ3jSDTeIhLhaX8aLuAW0QM6Wg6HdPzBYvYFCrV37F7hcmFkpKU4IpweHTAn9T9/R4Z/y8yYEKe4vxpRd+v2ElGl/7xw/+3yrDS/1n40g4e8tJMiCB5wR5hZnyay8C/JKHtYyXzzpfat2R2ZOcGEBCGm04acgJjPaNAhq+lVi5mvImUYfDQ5wdaZ4FRk/tBd1zxwc/Hrl2l3hZFs9go2djjbik9hdwW4lW1TN2WUehlr2mVOo/+UKhAUzXKvPbuaJESyYmGvZswkG8K7WuhmOXGXKl42Ra878mdZ4Ldo7o/ChRxpACpIAjsKqhUmz1/n10XSq8hllOQXlC9QgHStLXWZcVxjtS3sVq1qSYhAJghhzSlUWH3q/qk5v7zMBPYVNH8GdKg2MuXqwBkBgVAwVCwzSNlMN3Goik/i1Z9n3WKNGs5SIj0rLSnul0c=' 17 | 18 | deploy: 19 | - provider: script 20 | script: yarn gitpublish 21 | skip_cleanup: true 22 | on: 23 | branch: master 24 | repo: immutable-js-oss/immutable-js 25 | - provider: script 26 | skip_cleanup: true 27 | script: yarn deploy 28 | on: 29 | branch: master 30 | repo: immutable-js-oss/immutable-js 31 | tags: true 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2014-present, Facebook, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /__tests__/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jest": true 4 | }, 5 | "parserOptions": { 6 | "ecmaVersion": 6, 7 | "sourceType": "script" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /__tests__/ArraySeq.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import { Seq } from 'immutable'; 11 | 12 | describe('ArraySequence', () => { 13 | it('every is true when predicate is true for all entries', () => { 14 | expect(Seq([]).every(() => false)).toBe(true); 15 | expect(Seq([1, 2, 3]).every((v) => v > 0)).toBe(true); 16 | expect(Seq([1, 2, 3]).every((v) => v < 3)).toBe(false); 17 | }); 18 | 19 | it('some is true when predicate is true for any entry', () => { 20 | expect(Seq([]).some(() => true)).toBe(false); 21 | expect(Seq([1, 2, 3]).some((v) => v > 0)).toBe(true); 22 | expect(Seq([1, 2, 3]).some((v) => v < 3)).toBe(true); 23 | expect(Seq([1, 2, 3]).some((v) => v > 1)).toBe(true); 24 | expect(Seq([1, 2, 3]).some((v) => v < 0)).toBe(false); 25 | }); 26 | 27 | it('maps', () => { 28 | const i = Seq([1, 2, 3]); 29 | const m = i.map((x) => x + x).toArray(); 30 | expect(m).toEqual([2, 4, 6]); 31 | }); 32 | 33 | it('reduces', () => { 34 | const i = Seq([1, 2, 3]); 35 | const r = i.reduce((acc, x) => acc + x); 36 | expect(r).toEqual(6); 37 | }); 38 | 39 | it('efficiently chains iteration methods', () => { 40 | const i = Seq('abcdefghijklmnopqrstuvwxyz'.split('')); 41 | function studly(letter, index) { 42 | return index % 2 === 0 ? letter : letter.toUpperCase(); 43 | } 44 | const result = i 45 | .reverse() 46 | .take(10) 47 | .reverse() 48 | .take(5) 49 | .map(studly) 50 | .toArray() 51 | .join(''); 52 | expect(result).toBe('qRsTu'); 53 | }); 54 | 55 | it('counts from the end of the sequence on negative index', () => { 56 | const i = Seq([1, 2, 3, 4, 5, 6, 7]); 57 | expect(i.get(-1)).toBe(7); 58 | expect(i.get(-5)).toBe(3); 59 | expect(i.get(-9)).toBe(undefined); 60 | expect(i.get(-999, 1000)).toBe(1000); 61 | }); 62 | 63 | it('handles trailing holes', () => { 64 | const a = [1, 2, 3]; 65 | a.length = 10; 66 | const seq = Seq(a); 67 | expect(seq.size).toBe(10); 68 | expect(seq.toArray().length).toBe(10); 69 | expect(seq.map((x) => x * x).size).toBe(10); 70 | expect(seq.map((x) => x * x).toArray().length).toBe(10); 71 | expect(seq.skip(2).toArray().length).toBe(8); 72 | expect(seq.take(2).toArray().length).toBe(2); 73 | expect(seq.take(5).toArray().length).toBe(5); 74 | expect(seq.filter((x) => x % 2 === 1).toArray().length).toBe(2); 75 | expect(seq.toKeyedSeq().flip().size).toBe(10); 76 | expect(seq.toKeyedSeq().flip().flip().size).toBe(10); 77 | expect(seq.toKeyedSeq().flip().flip().toArray().length).toBe(10); 78 | }); 79 | 80 | it('can be iterated', () => { 81 | const a = [1, 2, 3]; 82 | const seq = Seq(a); 83 | const entries = seq.entries(); 84 | expect(entries.next()).toEqual({ value: [0, 1], done: false }); 85 | expect(entries.next()).toEqual({ value: [1, 2], done: false }); 86 | expect(entries.next()).toEqual({ value: [2, 3], done: false }); 87 | expect(entries.next()).toEqual({ value: undefined, done: true }); 88 | }); 89 | 90 | it('cannot be mutated after calling toArray', () => { 91 | const seq = Seq(['A', 'B', 'C']); 92 | 93 | const firstReverse = Seq(seq.toArray().reverse()); 94 | const secondReverse = Seq(seq.toArray().reverse()); 95 | 96 | expect(firstReverse.get(0)).toEqual('C'); 97 | expect(secondReverse.get(0)).toEqual('C'); 98 | }); 99 | }); 100 | -------------------------------------------------------------------------------- /__tests__/IndexedSeq.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import * as jasmineCheck from 'jasmine-check'; 11 | jasmineCheck.install(); 12 | 13 | import { Seq } from 'immutable'; 14 | 15 | describe('IndexedSequence', () => { 16 | it('maintains skipped offset', () => { 17 | const seq = Seq(['A', 'B', 'C', 'D', 'E']); 18 | 19 | // This is what we expect for IndexedSequences 20 | const operated = seq.skip(1); 21 | expect(operated.entrySeq().toArray()).toEqual([ 22 | [0, 'B'], 23 | [1, 'C'], 24 | [2, 'D'], 25 | [3, 'E'], 26 | ]); 27 | 28 | expect(operated.first()).toEqual('B'); 29 | }); 30 | 31 | it('reverses correctly', () => { 32 | const seq = Seq(['A', 'B', 'C', 'D', 'E']); 33 | 34 | // This is what we expect for IndexedSequences 35 | const operated = seq.reverse(); 36 | expect(operated.get(0)).toEqual('E'); 37 | expect(operated.get(1)).toEqual('D'); 38 | expect(operated.get(4)).toEqual('A'); 39 | 40 | expect(operated.first()).toEqual('E'); 41 | expect(operated.last()).toEqual('A'); 42 | }); 43 | 44 | it('negative indexes correctly', () => { 45 | const seq = Seq(['A', 'B', 'C', 'D', 'E']); 46 | 47 | expect(seq.first()).toEqual('A'); 48 | expect(seq.last()).toEqual('E'); 49 | expect(seq.get(-0)).toEqual('A'); 50 | expect(seq.get(2)).toEqual('C'); 51 | expect(seq.get(-2)).toEqual('D'); 52 | 53 | const indexes = seq.keySeq(); 54 | expect(indexes.first()).toEqual(0); 55 | expect(indexes.last()).toEqual(4); 56 | expect(indexes.get(-0)).toEqual(0); 57 | expect(indexes.get(2)).toEqual(2); 58 | expect(indexes.get(-2)).toEqual(3); 59 | }); 60 | }); 61 | -------------------------------------------------------------------------------- /__tests__/KeyedSeq.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import * as jasmineCheck from 'jasmine-check'; 11 | jasmineCheck.install(); 12 | 13 | import { Range, Seq } from 'immutable'; 14 | 15 | describe('KeyedSeq', () => { 16 | check.it('it iterates equivalently', [gen.array(gen.int)], (ints) => { 17 | const seq = Seq(ints); 18 | const keyed = seq.toKeyedSeq(); 19 | 20 | const seqEntries = seq.entries(); 21 | const keyedEntries = keyed.entries(); 22 | 23 | let seqStep, keyedStep; 24 | do { 25 | seqStep = seqEntries.next(); 26 | keyedStep = keyedEntries.next(); 27 | expect(keyedStep).toEqual(seqStep); 28 | } while (!seqStep.done); 29 | }); 30 | 31 | it('maintains keys', () => { 32 | const isEven = (x) => x % 2 === 0; 33 | const seq = Range(0, 100); 34 | 35 | // This is what we expect for IndexedSequences 36 | const operated = seq.filter(isEven).skip(10).take(5); 37 | expect(operated.entrySeq().toArray()).toEqual([ 38 | [0, 20], 39 | [1, 22], 40 | [2, 24], 41 | [3, 26], 42 | [4, 28], 43 | ]); 44 | 45 | // Where Keyed Sequences maintain keys. 46 | const keyed = seq.toKeyedSeq(); 47 | const keyedOperated = keyed.filter(isEven).skip(10).take(5); 48 | expect(keyedOperated.entrySeq().toArray()).toEqual([ 49 | [20, 20], 50 | [22, 22], 51 | [24, 24], 52 | [26, 26], 53 | [28, 28], 54 | ]); 55 | }); 56 | 57 | it('works with reverse', () => { 58 | const seq = Range(0, 100); 59 | 60 | // This is what we expect for IndexedSequences 61 | expect(seq.reverse().take(5).entrySeq().toArray()).toEqual([ 62 | [0, 99], 63 | [1, 98], 64 | [2, 97], 65 | [3, 96], 66 | [4, 95], 67 | ]); 68 | 69 | // Where Keyed Sequences maintain keys. 70 | expect(seq.toKeyedSeq().reverse().take(5).entrySeq().toArray()).toEqual([ 71 | [99, 99], 72 | [98, 98], 73 | [97, 97], 74 | [96, 96], 75 | [95, 95], 76 | ]); 77 | }); 78 | 79 | it('works with double reverse', () => { 80 | const seq = Range(0, 100); 81 | 82 | // This is what we expect for IndexedSequences 83 | expect( 84 | seq.reverse().skip(10).take(5).reverse().entrySeq().toArray() 85 | ).toEqual([ 86 | [0, 85], 87 | [1, 86], 88 | [2, 87], 89 | [3, 88], 90 | [4, 89], 91 | ]); 92 | 93 | // Where Keyed Sequences maintain keys. 94 | expect( 95 | seq.reverse().toKeyedSeq().skip(10).take(5).reverse().entrySeq().toArray() 96 | ).toEqual([ 97 | [14, 85], 98 | [13, 86], 99 | [12, 87], 100 | [11, 88], 101 | [10, 89], 102 | ]); 103 | }); 104 | }); 105 | -------------------------------------------------------------------------------- /__tests__/ListJS.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const { List } = require('../src/Immutable'); 9 | 10 | const NON_NUMBERS = { 11 | array: ['not', 'a', 'number'], 12 | NaN: NaN, 13 | object: { not: 'a number' }, 14 | string: 'not a number', 15 | }; 16 | 17 | describe('List', () => { 18 | describe('setSize()', () => { 19 | Object.keys(NON_NUMBERS).forEach((type) => { 20 | const nonNumber = NON_NUMBERS[type]; 21 | it(`considers a size argument of type '${type}' to be zero`, () => { 22 | const v1 = List.of(1, 2, 3); 23 | const v2 = v1.setSize(nonNumber); 24 | expect(v2.size).toBe(0); 25 | }); 26 | }); 27 | }); 28 | describe('slice()', () => { 29 | // Mimic the behavior of Array::slice() 30 | // http://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.slice 31 | Object.keys(NON_NUMBERS).forEach((type) => { 32 | const nonNumber = NON_NUMBERS[type]; 33 | it(`considers a begin argument of type '${type}' to be zero`, () => { 34 | const v1 = List.of('a', 'b', 'c'); 35 | const v2 = v1.slice(nonNumber, 2); 36 | expect(v2.size).toBe(2); 37 | expect(v2.first()).toBe('a'); 38 | expect(v2.rest().size).toBe(1); 39 | expect(v2.last()).toBe('b'); 40 | expect(v2.butLast().size).toBe(1); 41 | }); 42 | it(`considers an end argument of type '${type}' to be zero`, () => { 43 | const v1 = List.of('a', 'b', 'c'); 44 | const v2 = v1.slice(0, nonNumber); 45 | expect(v2.size).toBe(0); 46 | expect(v2.first()).toBe(undefined); 47 | expect(v2.rest().size).toBe(0); 48 | expect(v2.last()).toBe(undefined); 49 | expect(v2.butLast().size).toBe(0); 50 | }); 51 | }); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /__tests__/MultiRequire.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const Immutable1 = require('../src/Immutable'); 9 | 10 | jest.resetModules(); 11 | 12 | const Immutable2 = require('../src/Immutable'); 13 | 14 | describe('MultiRequire', () => { 15 | it('might require two different instances of Immutable', () => { 16 | expect(Immutable1).not.toBe(Immutable2); 17 | expect(Immutable1.Map({ a: 1 }).toJS()).toEqual({ a: 1 }); 18 | expect(Immutable2.Map({ a: 1 }).toJS()).toEqual({ a: 1 }); 19 | }); 20 | 21 | it('detects sequences', () => { 22 | const x = Immutable1.Map({ a: 1 }); 23 | const y = Immutable2.Map({ a: 1 }); 24 | expect(Immutable1.isCollection(y)).toBe(true); 25 | expect(Immutable2.isCollection(x)).toBe(true); 26 | }); 27 | 28 | it('detects records', () => { 29 | const R1 = Immutable1.Record({ a: 1 }); 30 | const R2 = Immutable2.Record({ a: 1 }); 31 | expect(Immutable1.Record.isRecord(R2())).toBe(true); 32 | expect(Immutable2.Record.isRecord(R1())).toBe(true); 33 | }); 34 | 35 | it('converts to JS when inter-nested', () => { 36 | const deep = Immutable1.Map({ 37 | a: 1, 38 | b: 2, 39 | c: Immutable2.Map({ 40 | x: 3, 41 | y: 4, 42 | z: Immutable1.Map(), 43 | }), 44 | }); 45 | 46 | expect(deep.toJS()).toEqual({ 47 | a: 1, 48 | b: 2, 49 | c: { 50 | x: 3, 51 | y: 4, 52 | z: {}, 53 | }, 54 | }); 55 | }); 56 | 57 | it('compares for equality', () => { 58 | const x = Immutable1.Map({ a: 1 }); 59 | const y = Immutable2.Map({ a: 1 }); 60 | expect(Immutable1.is(x, y)).toBe(true); 61 | expect(Immutable2.is(x, y)).toBe(true); 62 | }); 63 | 64 | it('flattens nested values', () => { 65 | const nested = Immutable1.List( 66 | Immutable2.List(Immutable1.List(Immutable2.List.of(1, 2))) 67 | ); 68 | 69 | expect(nested.flatten().toJS()).toEqual([1, 2]); 70 | }); 71 | 72 | it('detects types', () => { 73 | let c1 = Immutable1.Map(); 74 | let c2 = Immutable2.Map(); 75 | expect(Immutable1.Map.isMap(c2)).toBe(true); 76 | expect(Immutable2.Map.isMap(c1)).toBe(true); 77 | 78 | c1 = Immutable1.OrderedMap(); 79 | c2 = Immutable2.OrderedMap(); 80 | expect(Immutable1.OrderedMap.isOrderedMap(c2)).toBe(true); 81 | expect(Immutable2.OrderedMap.isOrderedMap(c1)).toBe(true); 82 | 83 | c1 = Immutable1.List(); 84 | c2 = Immutable2.List(); 85 | expect(Immutable1.List.isList(c2)).toBe(true); 86 | expect(Immutable2.List.isList(c1)).toBe(true); 87 | 88 | c1 = Immutable1.Stack(); 89 | c2 = Immutable2.Stack(); 90 | expect(Immutable1.Stack.isStack(c2)).toBe(true); 91 | expect(Immutable2.Stack.isStack(c1)).toBe(true); 92 | 93 | c1 = Immutable1.Set(); 94 | c2 = Immutable2.Set(); 95 | expect(Immutable1.Set.isSet(c2)).toBe(true); 96 | expect(Immutable2.Set.isSet(c1)).toBe(true); 97 | }); 98 | }); 99 | -------------------------------------------------------------------------------- /__tests__/ObjectSeq.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import { Seq } from 'immutable'; 11 | 12 | describe('ObjectSequence', () => { 13 | it('maps', () => { 14 | const i = Seq({ a: 'A', b: 'B', c: 'C' }); 15 | const m = i.map((x) => x + x).toObject(); 16 | expect(m).toEqual({ a: 'AA', b: 'BB', c: 'CC' }); 17 | }); 18 | 19 | it('reduces', () => { 20 | const i = Seq({ a: 'A', b: 'B', c: 'C' }); 21 | const r = i.reduce((acc, x) => acc + x, ''); 22 | expect(r).toEqual('ABC'); 23 | }); 24 | 25 | it('extracts keys', () => { 26 | const i = Seq({ a: 'A', b: 'B', c: 'C' }); 27 | const k = i.keySeq().toArray(); 28 | expect(k).toEqual(['a', 'b', 'c']); 29 | }); 30 | 31 | it('is reversable', () => { 32 | const i = Seq({ a: 'A', b: 'B', c: 'C' }); 33 | const k = i.reverse().toArray(); 34 | expect(k).toEqual([ 35 | ['c', 'C'], 36 | ['b', 'B'], 37 | ['a', 'A'], 38 | ]); 39 | }); 40 | 41 | it('is double reversable', () => { 42 | const i = Seq({ a: 'A', b: 'B', c: 'C' }); 43 | const k = i.reverse().reverse().toArray(); 44 | expect(k).toEqual([ 45 | ['a', 'A'], 46 | ['b', 'B'], 47 | ['c', 'C'], 48 | ]); 49 | }); 50 | 51 | it('can be iterated', () => { 52 | const obj = { a: 1, b: 2, c: 3 }; 53 | const seq = Seq(obj); 54 | const entries = seq.entries(); 55 | expect(entries.next()).toEqual({ value: ['a', 1], done: false }); 56 | expect(entries.next()).toEqual({ value: ['b', 2], done: false }); 57 | expect(entries.next()).toEqual({ value: ['c', 3], done: false }); 58 | expect(entries.next()).toEqual({ value: undefined, done: true }); 59 | }); 60 | 61 | it('cannot be mutated after calling toObject', () => { 62 | const seq = Seq({ a: 1, b: 2, c: 3 }); 63 | 64 | const obj = seq.toObject(); 65 | obj.c = 10; 66 | const seq2 = Seq(obj); 67 | 68 | expect(seq.get('c')).toEqual(3); 69 | expect(seq2.get('c')).toEqual(10); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /__tests__/Predicates.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import { 11 | is, 12 | isImmutable, 13 | isValueObject, 14 | List, 15 | Map, 16 | Set, 17 | Stack, 18 | } from 'immutable'; 19 | 20 | describe('isImmutable', () => { 21 | it('behaves as advertised', () => { 22 | expect(isImmutable([])).toBe(false); 23 | expect(isImmutable({})).toBe(false); 24 | expect(isImmutable(Map())).toBe(true); 25 | expect(isImmutable(List())).toBe(true); 26 | expect(isImmutable(Set())).toBe(true); 27 | expect(isImmutable(Stack())).toBe(true); 28 | expect(isImmutable(Map().asMutable())).toBe(true); 29 | }); 30 | }); 31 | 32 | describe('isValueObject', () => { 33 | it('behaves as advertised', () => { 34 | expect(isValueObject(null)).toBe(false); 35 | expect(isValueObject(123)).toBe(false); 36 | expect(isValueObject('abc')).toBe(false); 37 | expect(isValueObject([])).toBe(false); 38 | expect(isValueObject({})).toBe(false); 39 | expect(isValueObject(Map())).toBe(true); 40 | expect(isValueObject(List())).toBe(true); 41 | expect(isValueObject(Set())).toBe(true); 42 | expect(isValueObject(Stack())).toBe(true); 43 | expect(isValueObject(Map().asMutable())).toBe(true); 44 | }); 45 | 46 | it('works on custom types', () => { 47 | class MyValueType { 48 | v: any; 49 | 50 | constructor(val) { 51 | this.v = val; 52 | } 53 | 54 | equals(other) { 55 | return Boolean(other && this.v === other.v); 56 | } 57 | 58 | hashCode() { 59 | return this.v; 60 | } 61 | } 62 | 63 | expect(isValueObject(new MyValueType(123))).toBe(true); 64 | expect(is(new MyValueType(123), new MyValueType(123))).toBe(true); 65 | expect(Set().add(new MyValueType(123)).add(new MyValueType(123)).size).toBe( 66 | 1 67 | ); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /__tests__/RecordJS.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const { Record } = require('immutable'); 9 | 10 | describe('Record', () => { 11 | it('defines a record factory', () => { 12 | const MyType = Record({ a: 1, b: 2, c: 3 }); 13 | 14 | const t = MyType(); 15 | const t2 = t.set('a', 10); 16 | 17 | expect(t.a).toBe(1); 18 | expect(t2.a).toBe(10); 19 | }); 20 | 21 | it('can have mutations apply', () => { 22 | const MyType = Record({ a: 1, b: 2, c: 3 }); 23 | 24 | const t = MyType(); 25 | 26 | expect(() => { 27 | t.a = 10; 28 | }).toThrow(); 29 | 30 | const t2 = t.withMutations((mt) => { 31 | mt.a = 10; 32 | mt.b = 20; 33 | mt.c = 30; 34 | }); 35 | 36 | expect(t.a).toBe(1); 37 | expect(t2.a).toBe(10); 38 | }); 39 | 40 | it('can be subclassed', () => { 41 | class Alphabet extends Record({ a: 1, b: 2, c: 3 }) { 42 | soup() { 43 | return this.a + this.b + this.c; 44 | } 45 | } 46 | 47 | // Note: `new` is only used because of `class` 48 | const t = new Alphabet(); 49 | const t2 = t.set('b', 200); 50 | 51 | expect(t instanceof Record); 52 | expect(t instanceof Alphabet); 53 | expect(t.soup()).toBe(6); 54 | expect(t2.soup()).toBe(204); 55 | 56 | // Uses class name as descriptive name 57 | expect(Record.getDescriptiveName(t)).toBe('Alphabet'); 58 | 59 | // Uses display name over class name 60 | class NotADisplayName extends Record({ x: 1 }, 'DisplayName') {} 61 | const t3 = new NotADisplayName(); 62 | expect(Record.getDescriptiveName(t3)).toBe('DisplayName'); 63 | }); 64 | 65 | it('can be cleared', () => { 66 | const MyType = Record({ a: 1, b: 2, c: 3 }); 67 | let t = MyType({ c: 'cats' }); 68 | 69 | expect(t.c).toBe('cats'); 70 | t = t.clear(); 71 | expect(t.c).toBe(3); 72 | 73 | const MyType2 = Record({ d: 4, e: 5, f: 6 }); 74 | let t2 = MyType2({ d: 'dogs' }); 75 | 76 | expect(t2.d).toBe('dogs'); 77 | t2 = t2.clear(); 78 | expect(t2.d).toBe(4); 79 | }); 80 | }); 81 | -------------------------------------------------------------------------------- /__tests__/Repeat.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import { Repeat } from 'immutable'; 11 | 12 | describe('Repeat', () => { 13 | it('fixed repeat', () => { 14 | const v = Repeat('wtf', 3); 15 | expect(v.size).toBe(3); 16 | expect(v.first()).toBe('wtf'); 17 | expect(v.rest().toArray()).toEqual(['wtf', 'wtf']); 18 | expect(v.last()).toBe('wtf'); 19 | expect(v.butLast().toArray()).toEqual(['wtf', 'wtf']); 20 | expect(v.toArray()).toEqual(['wtf', 'wtf', 'wtf']); 21 | expect(v.join()).toEqual('wtf,wtf,wtf'); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /__tests__/Seq.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import { isCollection, isIndexed, Seq } from 'immutable'; 11 | 12 | describe('Seq', () => { 13 | it('returns undefined if empty and first is called without default argument', () => { 14 | expect(Seq().first()).toBeUndefined(); 15 | }); 16 | 17 | it('returns undefined if empty and last is called without default argument', () => { 18 | expect(Seq().last()).toBeUndefined(); 19 | }); 20 | 21 | it('returns default value if empty and first is called with default argument', () => { 22 | expect(Seq().first({})).toEqual({}); 23 | }); 24 | 25 | it('returns default value if empty and last is called with default argument', () => { 26 | expect(Seq().last({})).toEqual({}); 27 | }); 28 | 29 | it('can be empty', () => { 30 | expect(Seq().size).toBe(0); 31 | }); 32 | 33 | it('accepts an array', () => { 34 | expect(Seq([1, 2, 3]).size).toBe(3); 35 | }); 36 | 37 | it('accepts an object', () => { 38 | expect(Seq({ a: 1, b: 2, c: 3 }).size).toBe(3); 39 | }); 40 | 41 | it('accepts an object with a next property', () => { 42 | expect(Seq({ a: 1, b: 2, next: (_) => _ }).size).toBe(3); 43 | }); 44 | 45 | it('accepts a collection string', () => { 46 | expect(Seq('foo').size).toBe(3); 47 | }); 48 | 49 | it('accepts arbitrary objects', () => { 50 | function Foo() { 51 | this.bar = 'bar'; 52 | this.baz = 'baz'; 53 | } 54 | expect(Seq(new Foo()).size).toBe(2); 55 | }); 56 | 57 | it('accepts another sequence', () => { 58 | const seq = Seq([1, 2, 3]); 59 | expect(Seq(seq).size).toBe(3); 60 | }); 61 | 62 | it('accepts a string', () => { 63 | const seq = Seq('abc'); 64 | expect(seq.size).toBe(3); 65 | expect(seq.get(1)).toBe('b'); 66 | expect(seq.join('')).toBe('abc'); 67 | }); 68 | 69 | it('accepts an array-like', () => { 70 | const seq = Seq({ length: 2, 0: 'a', 1: 'b' }); 71 | expect(isIndexed(seq)).toBe(true); 72 | expect(seq.size).toBe(2); 73 | expect(seq.get(1)).toBe('b'); 74 | 75 | const map = Seq({ length: 1, foo: 'bar' }); 76 | expect(isIndexed(map)).toBe(false); 77 | expect(map.size).toBe(2); 78 | expect(map.get('foo')).toBe('bar'); 79 | 80 | const empty = Seq({ length: 0 }); 81 | expect(isIndexed(empty)).toBe(true); 82 | expect(empty.size).toEqual(0); 83 | }); 84 | 85 | it('does not accept a scalar', () => { 86 | expect(() => { 87 | Seq(3 as any); 88 | }).toThrow( 89 | 'Expected Array or collection object of values, or keyed object: 3' 90 | ); 91 | }); 92 | 93 | it('detects sequences', () => { 94 | const seq = Seq([1, 2, 3]); 95 | expect(Seq.isSeq(seq)).toBe(true); 96 | expect(isCollection(seq)).toBe(true); 97 | }); 98 | 99 | it('Does not infinite loop when sliced with NaN', () => { 100 | const list = Seq([1, 2, 3, 4, 5]); 101 | expect(list.slice(0, NaN).toJS()).toEqual([]); 102 | expect(list.slice(NaN).toJS()).toEqual([1, 2, 3, 4, 5]); 103 | }); 104 | 105 | it('Does not infinite loop when spliced with negative number #559', () => { 106 | const dog = Seq(['d', 'o', 'g']); 107 | const dg = dog.filter((c) => c !== 'o'); 108 | const dig = (dg as any).splice(-1, 0, 'i'); 109 | expect(dig.toJS()).toEqual(['d', 'i', 'g']); 110 | }); 111 | 112 | it('Does not infinite loop when an undefined number is passed to take', () => { 113 | const list = Seq([1, 2, 3, 4, 5]); 114 | expect(list.take(NaN).toJS()).toEqual([]); 115 | }); 116 | 117 | it('Converts deeply toJS after converting to entries', () => { 118 | const list = Seq([Seq([1, 2]), Seq({ a: 'z' })]); 119 | expect(list.entrySeq().toJS()).toEqual([ 120 | [0, [1, 2]], 121 | [1, { a: 'z' }], 122 | ]); 123 | 124 | const map = Seq({ x: Seq([1, 2]), y: Seq({ a: 'z' }) }); 125 | expect(map.entrySeq().toJS()).toEqual([ 126 | ['x', [1, 2]], 127 | ['y', { a: 'z' }], 128 | ]); 129 | }); 130 | }); 131 | -------------------------------------------------------------------------------- /__tests__/__snapshots__/Record.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Record does not accept a Record as constructor 1`] = `"Can not call \`Record\` with an immutable Record as default values. Use a plain javascript object instead."`; 4 | 5 | exports[`Record does not accept a non object as constructor 1`] = `"Can not call \`Record\` with a non-object as default values. Use a plain javascript object instead."`; 6 | 7 | exports[`Record does not accept an immutable object that is not a Record as constructor 1`] = `"Can not call \`Record\` with an immutable Collection as default values. Use a plain javascript object instead."`; 8 | -------------------------------------------------------------------------------- /__tests__/count.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import { Range, Seq } from 'immutable'; 11 | 12 | describe('count', () => { 13 | it('counts sequences with known lengths', () => { 14 | expect(Seq([1, 2, 3, 4, 5]).size).toBe(5); 15 | expect(Seq([1, 2, 3, 4, 5]).count()).toBe(5); 16 | }); 17 | 18 | it('counts sequences with unknown lengths, resulting in a cached size', () => { 19 | const seq = Seq([1, 2, 3, 4, 5, 6]).filter((x) => x % 2 === 0); 20 | expect(seq.size).toBe(undefined); 21 | expect(seq.count()).toBe(3); 22 | expect(seq.size).toBe(3); 23 | }); 24 | 25 | it('counts sequences with a specific predicate', () => { 26 | const seq = Seq([1, 2, 3, 4, 5, 6]); 27 | expect(seq.size).toBe(6); 28 | expect(seq.count((x) => x > 3)).toBe(3); 29 | }); 30 | 31 | describe('countBy', () => { 32 | it('counts by keyed sequence', () => { 33 | const grouped = Seq({ a: 1, b: 2, c: 3, d: 4 }).countBy((x) => x % 2); 34 | expect(grouped.toJS()).toEqual({ 1: 2, 0: 2 }); 35 | expect(grouped.get(1)).toEqual(2); 36 | }); 37 | 38 | it('counts by indexed sequence', () => { 39 | expect( 40 | Seq([1, 2, 3, 4, 5, 6]) 41 | .countBy((x) => x % 2) 42 | .toJS() 43 | ).toEqual({ 1: 3, 0: 3 }); 44 | }); 45 | 46 | it('counts by specific keys', () => { 47 | expect( 48 | Seq([1, 2, 3, 4, 5, 6]) 49 | .countBy((x) => (x % 2 ? 'odd' : 'even')) 50 | .toJS() 51 | ).toEqual({ odd: 3, even: 3 }); 52 | }); 53 | }); 54 | 55 | describe('isEmpty', () => { 56 | it('is O(1) on sequences with known lengths', () => { 57 | expect(Seq([1, 2, 3, 4, 5]).size).toBe(5); 58 | expect(Seq([1, 2, 3, 4, 5]).isEmpty()).toBe(false); 59 | expect(Seq().size).toBe(0); 60 | expect(Seq().isEmpty()).toBe(true); 61 | }); 62 | 63 | it('lazily evaluates Seq with unknown length', () => { 64 | let seq = Seq([1, 2, 3, 4, 5, 6]).filter((x) => x % 2 === 0); 65 | expect(seq.size).toBe(undefined); 66 | expect(seq.isEmpty()).toBe(false); 67 | expect(seq.size).toBe(undefined); 68 | 69 | seq = Seq([1, 2, 3, 4, 5, 6]).filter((x) => x > 10); 70 | expect(seq.size).toBe(undefined); 71 | expect(seq.isEmpty()).toBe(true); 72 | expect(seq.size).toBe(undefined); 73 | }); 74 | 75 | it('with infinitely long sequences of known length', () => { 76 | const seq = Range(); 77 | expect(seq.size).toBe(Infinity); 78 | expect(seq.isEmpty()).toBe(false); 79 | }); 80 | 81 | it('with infinitely long sequences of unknown length', () => { 82 | const seq = Range().filter((x) => x % 2 === 0); 83 | expect(seq.size).toBe(undefined); 84 | expect(seq.isEmpty()).toBe(false); 85 | expect(seq.size).toBe(undefined); 86 | }); 87 | }); 88 | }); 89 | -------------------------------------------------------------------------------- /__tests__/find.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import * as jasmineCheck from 'jasmine-check'; 11 | jasmineCheck.install(); 12 | 13 | import { List, Range, Seq } from 'immutable'; 14 | 15 | describe('find', () => { 16 | it('find returns notSetValue when match is not found', () => { 17 | expect( 18 | Seq([1, 2, 3, 4, 5, 6]).find( 19 | function () { 20 | return false; 21 | }, 22 | null, 23 | 9 24 | ) 25 | ).toEqual(9); 26 | }); 27 | 28 | it('findEntry returns notSetValue when match is not found', () => { 29 | expect( 30 | Seq([1, 2, 3, 4, 5, 6]).findEntry( 31 | function () { 32 | return false; 33 | }, 34 | null, 35 | 9 36 | ) 37 | ).toEqual(9); 38 | }); 39 | 40 | it('findLastEntry returns notSetValue when match is not found', () => { 41 | expect( 42 | Seq([1, 2, 3, 4, 5, 6]).findLastEntry( 43 | function () { 44 | return false; 45 | }, 46 | null, 47 | 9 48 | ) 49 | ).toEqual(9); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /__tests__/fromJS.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | // tslint:disable-next-line:no-var-requires 11 | const vm = require('vm'); 12 | 13 | import { Iterable, fromJS } from '../'; 14 | 15 | describe('fromJS', () => { 16 | it('is iterable outside of a vm', () => { 17 | expect(Iterable.isIterable(fromJS({}))).toBe(true); 18 | }); 19 | 20 | it('is iterable inside of a vm', () => { 21 | vm.runInNewContext( 22 | ` 23 | expect(Iterable.isIterable(fromJS({}))).toBe(true); 24 | `, 25 | { 26 | expect, 27 | Iterable, 28 | fromJS, 29 | }, 30 | {} 31 | ); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /__tests__/get.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import { Range } from 'immutable'; 11 | 12 | describe('get', () => { 13 | it('gets any index', () => { 14 | const seq = Range(0, 100); 15 | expect(seq.get(20)).toBe(20); 16 | }); 17 | 18 | it('gets first', () => { 19 | const seq = Range(0, 100); 20 | expect(seq.first()).toBe(0); 21 | }); 22 | 23 | it('gets last', () => { 24 | const seq = Range(0, 100); 25 | expect(seq.last()).toBe(99); 26 | }); 27 | 28 | it('gets any index after reversing', () => { 29 | const seq = Range(0, 100).reverse(); 30 | expect(seq.get(20)).toBe(79); 31 | }); 32 | 33 | it('gets first after reversing', () => { 34 | const seq = Range(0, 100).reverse(); 35 | expect(seq.first()).toBe(99); 36 | }); 37 | 38 | it('gets last after reversing', () => { 39 | const seq = Range(0, 100).reverse(); 40 | expect(seq.last()).toBe(0); 41 | }); 42 | 43 | it('gets any index when size is unknown', () => { 44 | const seq = Range(0, 100).filter((x) => x % 2 === 1); 45 | expect(seq.get(20)).toBe(41); 46 | }); 47 | 48 | it('gets first when size is unknown', () => { 49 | const seq = Range(0, 100).filter((x) => x % 2 === 1); 50 | expect(seq.first()).toBe(1); 51 | }); 52 | 53 | it('gets last when size is unknown', () => { 54 | const seq = Range(0, 100).filter((x) => x % 2 === 1); 55 | expect(seq.last()).toBe(99); // Note: this is O(N) 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /__tests__/groupBy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import { Collection, Map, Seq } from 'immutable'; 11 | 12 | describe('groupBy', () => { 13 | it('groups keyed sequence', () => { 14 | const grouped = Seq({ a: 1, b: 2, c: 3, d: 4 }).groupBy((x) => x % 2); 15 | expect(grouped.toJS()).toEqual({ 1: { a: 1, c: 3 }, 0: { b: 2, d: 4 } }); 16 | 17 | // Each group should be a keyed sequence, not an indexed sequence 18 | const firstGroup = grouped.get(1); 19 | expect(firstGroup && firstGroup.toArray()).toEqual([ 20 | ['a', 1], 21 | ['c', 3], 22 | ]); 23 | }); 24 | 25 | it('groups indexed sequence', () => { 26 | expect( 27 | Seq([1, 2, 3, 4, 5, 6]) 28 | .groupBy((x) => x % 2) 29 | .toJS() 30 | ).toEqual({ 1: [1, 3, 5], 0: [2, 4, 6] }); 31 | }); 32 | 33 | it('groups to keys', () => { 34 | expect( 35 | Seq([1, 2, 3, 4, 5, 6]) 36 | .groupBy((x) => (x % 2 ? 'odd' : 'even')) 37 | .toJS() 38 | ).toEqual({ odd: [1, 3, 5], even: [2, 4, 6] }); 39 | }); 40 | 41 | it('groups indexed sequences, maintaining indicies when keyed sequences', () => { 42 | expect( 43 | Seq([1, 2, 3, 4, 5, 6]) 44 | .groupBy((x) => x % 2) 45 | .toJS() 46 | ).toEqual({ 1: [1, 3, 5], 0: [2, 4, 6] }); 47 | expect( 48 | Seq([1, 2, 3, 4, 5, 6]) 49 | .toKeyedSeq() 50 | .groupBy((x) => x % 2) 51 | .toJS() 52 | ).toEqual({ 1: { 0: 1, 2: 3, 4: 5 }, 0: { 1: 2, 3: 4, 5: 6 } }); 53 | }); 54 | 55 | it('has groups that can be mapped', () => { 56 | expect( 57 | Seq([1, 2, 3, 4, 5, 6]) 58 | .groupBy((x) => x % 2) 59 | .map((group) => group.map((value) => value * 10)) 60 | .toJS() 61 | ).toEqual({ 1: [10, 30, 50], 0: [20, 40, 60] }); 62 | }); 63 | 64 | it('returns an ordered map from an ordered collection', () => { 65 | const seq = Seq(['Z', 'Y', 'X', 'Z', 'Y', 'X']); 66 | expect(Collection.isOrdered(seq)).toBe(true); 67 | const seqGroups = seq.groupBy((x) => x); 68 | expect(Collection.isOrdered(seqGroups)).toBe(true); 69 | 70 | const map = Map({ x: 1, y: 2 }); 71 | expect(Collection.isOrdered(map)).toBe(false); 72 | const mapGroups = map.groupBy((x) => x); 73 | expect(Collection.isOrdered(mapGroups)).toBe(false); 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /__tests__/hasIn.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import { fromJS, hasIn, List, Map } from 'immutable'; 11 | 12 | describe('hasIn', () => { 13 | it('deep has', () => { 14 | const m = fromJS({ a: { b: { c: 10, d: undefined } } }); 15 | expect(m.hasIn(['a', 'b', 'c'])).toEqual(true); 16 | expect(m.hasIn(['a', 'b', 'd'])).toEqual(true); 17 | expect(m.hasIn(['a', 'b', 'z'])).toEqual(false); 18 | expect(m.hasIn(['a', 'y', 'z'])).toEqual(false); 19 | expect(hasIn(m, ['a', 'b', 'c'])).toEqual(true); 20 | expect(hasIn(m, ['a', 'b', 'z'])).toEqual(false); 21 | }); 22 | 23 | it('deep has with list as keyPath', () => { 24 | const m = fromJS({ a: { b: { c: 10 } } }); 25 | expect(m.hasIn(fromJS(['a', 'b', 'c']))).toEqual(true); 26 | expect(m.hasIn(fromJS(['a', 'b', 'z']))).toEqual(false); 27 | expect(m.hasIn(fromJS(['a', 'y', 'z']))).toEqual(false); 28 | expect(hasIn(m, fromJS(['a', 'b', 'c']))).toEqual(true); 29 | expect(hasIn(m, fromJS(['a', 'y', 'z']))).toEqual(false); 30 | }); 31 | 32 | it('deep has throws without list or array-like', () => { 33 | // need to cast these as TypeScript first prevents us from such clownery. 34 | expect(() => Map().hasIn(undefined as any)).toThrow( 35 | 'Invalid keyPath: expected Ordered Collection or Array: undefined' 36 | ); 37 | expect(() => Map().hasIn({ a: 1, b: 2 } as any)).toThrow( 38 | 'Invalid keyPath: expected Ordered Collection or Array: [object Object]' 39 | ); 40 | expect(() => Map().hasIn('abc' as any)).toThrow( 41 | 'Invalid keyPath: expected Ordered Collection or Array: abc' 42 | ); 43 | expect(() => hasIn(Map(), 'abc' as any)).toThrow( 44 | 'Invalid keyPath: expected Ordered Collection or Array: abc' 45 | ); 46 | }); 47 | 48 | it('deep has does not throw if non-readable path', () => { 49 | const deep = Map({ 50 | key: { regular: 'jsobj' }, 51 | list: List([Map({ num: 10 })]), 52 | }); 53 | expect(deep.hasIn(['key', 'foo', 'item'])).toBe(false); 54 | expect(deep.hasIn(['list', 0, 'num', 'badKey'])).toBe(false); 55 | expect(hasIn(deep, ['key', 'foo', 'item'])).toBe(false); 56 | expect(hasIn(deep, ['list', 0, 'num', 'badKey'])).toBe(false); 57 | }); 58 | 59 | it('deep has in plain Object and Array', () => { 60 | const m = { a: { b: { c: [10, undefined], d: undefined } } }; 61 | expect(hasIn(m, ['a', 'b', 'c', 0])).toEqual(true); 62 | expect(hasIn(m, ['a', 'b', 'c', 1])).toEqual(true); 63 | expect(hasIn(m, ['a', 'b', 'c', 2])).toEqual(false); 64 | expect(hasIn(m, ['a', 'b', 'd'])).toEqual(true); 65 | expect(hasIn(m, ['a', 'b', 'z'])).toEqual(false); 66 | expect(hasIn(m, ['a', 'b', 'z'])).toEqual(false); 67 | }); 68 | }); 69 | -------------------------------------------------------------------------------- /__tests__/hash.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import * as jasmineCheck from 'jasmine-check'; 11 | jasmineCheck.install(); 12 | 13 | import { hash } from 'immutable'; 14 | 15 | describe('hash', () => { 16 | it('stable hash of well known values', () => { 17 | expect(hash(true)).toBe(0x42108421); 18 | expect(hash(false)).toBe(0x42108420); 19 | expect(hash(0)).toBe(0); 20 | expect(hash(null)).toBe(0x42108422); 21 | expect(hash(undefined)).toBe(0x42108423); 22 | expect(hash('a')).toBe(97); 23 | expect(hash('immutable-js')).toBe(510203252); 24 | expect(hash(123)).toBe(123); 25 | }); 26 | 27 | it('generates different hashes for decimal values', () => { 28 | expect(hash(123.456)).toBe(884763256); 29 | expect(hash(123.4567)).toBe(887769707); 30 | }); 31 | 32 | it('generates different hashes for different objects', () => { 33 | const objA = {}; 34 | const objB = {}; 35 | expect(hash(objA)).toBe(hash(objA)); 36 | expect(hash(objA)).not.toBe(hash(objB)); 37 | }); 38 | 39 | it('generates different hashes for different symbols', () => { 40 | const symA = Symbol(); 41 | const symB = Symbol(); 42 | expect(hash(symA)).toBe(hash(symA)); 43 | expect(hash(symA)).not.toBe(hash(symB)); 44 | }); 45 | 46 | it('generates different hashes for different functions', () => { 47 | const funA = () => { 48 | return; 49 | }; 50 | const funB = () => { 51 | return; 52 | }; 53 | expect(hash(funA)).toBe(hash(funA)); 54 | expect(hash(funA)).not.toBe(hash(funB)); 55 | }); 56 | 57 | const genValue = gen.oneOf([gen.string, gen.int]); 58 | 59 | check.it('generates unsigned 31-bit integers', [genValue], (value) => { 60 | const hashVal = hash(value); 61 | expect(Number.isInteger(hashVal)).toBe(true); 62 | expect(hashVal).toBeGreaterThan(-Math.pow(2, 31)); 63 | expect(hashVal).toBeLessThan(Math.pow(2, 31)); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /__tests__/interpose.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import { Range } from 'immutable'; 11 | 12 | describe('interpose', () => { 13 | it('separates with a value', () => { 14 | const range = Range(10, 15); 15 | const interposed = range.interpose(0); 16 | expect(interposed.toArray()).toEqual([10, 0, 11, 0, 12, 0, 13, 0, 14]); 17 | }); 18 | 19 | it('can be iterated', () => { 20 | const range = Range(10, 15); 21 | const interposed = range.interpose(0); 22 | const values = interposed.values(); 23 | expect(values.next()).toEqual({ value: 10, done: false }); 24 | expect(values.next()).toEqual({ value: 0, done: false }); 25 | expect(values.next()).toEqual({ value: 11, done: false }); 26 | expect(values.next()).toEqual({ value: 0, done: false }); 27 | expect(values.next()).toEqual({ value: 12, done: false }); 28 | expect(values.next()).toEqual({ value: 0, done: false }); 29 | expect(values.next()).toEqual({ value: 13, done: false }); 30 | expect(values.next()).toEqual({ value: 0, done: false }); 31 | expect(values.next()).toEqual({ value: 14, done: false }); 32 | expect(values.next()).toEqual({ value: undefined, done: true }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /__tests__/issues.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | declare var Symbol: any; 11 | import { List, OrderedMap, OrderedSet, Record, Seq, Set } from 'immutable'; 12 | 13 | describe('Issue #1175', () => { 14 | it('invalid hashCode() response should not infinitly recurse', () => { 15 | class BadHash { 16 | equals() { 17 | return false; 18 | } 19 | hashCode() { 20 | return 2 ** 32; 21 | } 22 | } 23 | 24 | const set = Set([new BadHash()]); 25 | expect(set.size).toEqual(1); 26 | }); 27 | }); 28 | 29 | describe('Issue #1188', () => { 30 | it('Removing items from OrderedSet should return OrderedSet', () => { 31 | const orderedSet = OrderedSet(['one', 'two', 'three']); 32 | const emptyOrderedSet = orderedSet.subtract(['two', 'three', 'one']); 33 | expect(OrderedSet.isOrderedSet(emptyOrderedSet)).toBe(true); 34 | }); 35 | }); 36 | 37 | describe('Issue #1220 : Seq.rest() throws an exception when invoked on a single item sequence ', () => { 38 | it('should be iterable', () => { 39 | // Helper for this test 40 | const ITERATOR_SYMBOL = 41 | (typeof Symbol === 'function' && Symbol.iterator) || '@@iterator'; 42 | 43 | const r = Seq([1]).rest(); 44 | const i = r[ITERATOR_SYMBOL](); 45 | expect(i.next()).toEqual({ value: undefined, done: true }); 46 | }); 47 | }); 48 | 49 | describe('Issue #1245', () => { 50 | it('should return empty collection after takeLast(0)', () => { 51 | const size = List(['a', 'b', 'c']).takeLast(0).size; 52 | expect(size).toEqual(0); 53 | }); 54 | }); 55 | 56 | describe('Issue #1262', () => { 57 | it('Set.subtract should accept an array', () => { 58 | const MyType = Record({ val: 1 }); 59 | const set1 = Set([ 60 | MyType({ val: 1 }), 61 | MyType({ val: 2 }), 62 | MyType({ val: 3 }), 63 | ]); 64 | const set2 = set1.subtract([MyType({ val: 2 })]); 65 | const set3 = set1.subtract(List([MyType({ val: 2 })])); 66 | expect(set2).toEqual(set3); 67 | }); 68 | }); 69 | 70 | describe('Issue #1287', () => { 71 | it('should skip all items in OrderedMap when skipping Infinity', () => { 72 | const size = OrderedMap([['a', 1]]).skip(Infinity).size; 73 | expect(size).toEqual(0); 74 | }); 75 | }); 76 | 77 | describe('Issue #1247', () => { 78 | it('Records should not be considered altered after creation', () => { 79 | const R = Record({ a: 1 }); 80 | const r = new R(); 81 | expect(r.wasAltered()).toBe(false); 82 | }); 83 | }); 84 | 85 | describe('Issue #1252', () => { 86 | it('should be toString-able even if it contains a value which is not', () => { 87 | const prototypelessObj = Object.create(null); 88 | const list = List([prototypelessObj]); 89 | expect(list.toString()).toBe('List [ {} ]'); 90 | }); 91 | }); 92 | 93 | describe('Issue #1293', () => { 94 | it('merge() should not deeply coerce values', () => { 95 | const State = Record({ foo: 'bar' as any, biz: 'baz' }); 96 | const deepObject = { qux: 'quux' }; 97 | 98 | const firstState = State({ foo: deepObject }); 99 | const secondState = State().merge({ foo: deepObject }); 100 | 101 | expect(secondState).toEqual(firstState); 102 | }); 103 | }); 104 | 105 | describe('Issue #1643', () => { 106 | [ 107 | ['a string', 'test'], 108 | ['a number', 5], 109 | ['null', null], 110 | ['undefined', undefined], 111 | ['a boolean', true], 112 | ['an object', {}], 113 | ['an array', []], 114 | ['a function', () => null], 115 | ].forEach(([label, value]) => { 116 | class MyClass { 117 | valueOf() { 118 | return value; 119 | } 120 | } 121 | 122 | it(`Collection#hashCode() should handle objects that return ${label} for valueOf`, () => { 123 | const set = Set().add(new MyClass()); 124 | set.hashCode(); 125 | }); 126 | }); 127 | }); 128 | 129 | describe('Issue #1785', () => { 130 | const emptyRecord = Record({})(); 131 | 132 | expect(emptyRecord.merge({ id: 1 })).toBe(emptyRecord); 133 | }); 134 | -------------------------------------------------------------------------------- /__tests__/join.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import jasmineCheck = require('jasmine-check'); 11 | jasmineCheck.install(); 12 | 13 | import { Seq } from 'immutable'; 14 | 15 | describe('join', () => { 16 | it('string-joins sequences with commas by default', () => { 17 | expect(Seq([1, 2, 3, 4, 5]).join()).toBe('1,2,3,4,5'); 18 | }); 19 | 20 | it('string-joins sequences with any string', () => { 21 | expect(Seq([1, 2, 3, 4, 5]).join('foo')).toBe('1foo2foo3foo4foo5'); 22 | }); 23 | 24 | it('string-joins sequences with empty string', () => { 25 | expect(Seq([1, 2, 3, 4, 5]).join('')).toBe('12345'); 26 | }); 27 | 28 | it('joins sparse-sequences like Array.join', () => { 29 | const a = [ 30 | 1, 31 | undefined, 32 | 2, 33 | undefined, 34 | 3, 35 | undefined, 36 | 4, 37 | undefined, 38 | 5, 39 | undefined, 40 | undefined, 41 | ]; 42 | expect(Seq(a).join()).toBe(a.join()); 43 | }); 44 | 45 | check.it( 46 | 'behaves the same as Array.join', 47 | [gen.array(gen.primitive), gen.primitive], 48 | (array, joiner) => { 49 | expect(Seq(array).join(joiner)).toBe(array.join(joiner)); 50 | } 51 | ); 52 | }); 53 | -------------------------------------------------------------------------------- /__tests__/minmax.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import * as jasmineCheck from 'jasmine-check'; 11 | jasmineCheck.install(); 12 | 13 | import { is, Seq } from 'immutable'; 14 | 15 | const genHeterogeneousishArray = gen.oneOf([ 16 | gen.array(gen.oneOf([gen.string, gen.undefined])), 17 | gen.array(gen.oneOf([gen.int, gen.NaN])), 18 | ]); 19 | 20 | describe('max', () => { 21 | it('returns max in a sequence', () => { 22 | expect(Seq([1, 9, 2, 8, 3, 7, 4, 6, 5]).max()).toBe(9); 23 | }); 24 | 25 | it('accepts a comparator', () => { 26 | expect(Seq([1, 9, 2, 8, 3, 7, 4, 6, 5]).max((a, b) => b - a)).toBe(1); 27 | }); 28 | 29 | it('by a mapper', () => { 30 | const family = Seq([ 31 | { name: 'Oakley', age: 7 }, 32 | { name: 'Dakota', age: 7 }, 33 | { name: 'Casey', age: 34 }, 34 | { name: 'Avery', age: 34 }, 35 | ]); 36 | expect(family.maxBy((p) => p.age)).toBe(family.get(2)); 37 | }); 38 | 39 | it('by a mapper and a comparator', () => { 40 | const family = Seq([ 41 | { name: 'Oakley', age: 7 }, 42 | { name: 'Dakota', age: 7 }, 43 | { name: 'Casey', age: 34 }, 44 | { name: 'Avery', age: 34 }, 45 | ]); 46 | expect( 47 | family.maxBy( 48 | (p) => p.age, 49 | (a, b) => b - a 50 | ) 51 | ).toBe(family.get(0)); 52 | }); 53 | 54 | it('surfaces NaN, null, and undefined', () => { 55 | expect(is(NaN, Seq([1, 2, 3, 4, 5, NaN]).max())).toBe(true); 56 | expect(is(NaN, Seq([NaN, 1, 2, 3, 4, 5]).max())).toBe(true); 57 | expect(is(null, Seq(['A', 'B', 'C', 'D', null]).max())).toBe(true); 58 | expect(is(null, Seq([null, 'A', 'B', 'C', 'D']).max())).toBe(true); 59 | }); 60 | 61 | it('null treated as 0 in default iterator', () => { 62 | expect(is(2, Seq([-1, -2, null, 1, 2]).max())).toBe(true); 63 | }); 64 | 65 | check.it('is not dependent on order', [genHeterogeneousishArray], (vals) => { 66 | expect(is(Seq(shuffle(vals.slice())).max(), Seq(vals).max())).toEqual(true); 67 | }); 68 | }); 69 | 70 | describe('min', () => { 71 | it('returns min in a sequence', () => { 72 | expect(Seq([1, 9, 2, 8, 3, 7, 4, 6, 5]).min()).toBe(1); 73 | }); 74 | 75 | it('accepts a comparator', () => { 76 | expect(Seq([1, 9, 2, 8, 3, 7, 4, 6, 5]).min((a, b) => b - a)).toBe(9); 77 | }); 78 | 79 | it('by a mapper', () => { 80 | const family = Seq([ 81 | { name: 'Oakley', age: 7 }, 82 | { name: 'Dakota', age: 7 }, 83 | { name: 'Casey', age: 34 }, 84 | { name: 'Avery', age: 34 }, 85 | ]); 86 | expect(family.minBy((p) => p.age)).toBe(family.get(0)); 87 | }); 88 | 89 | it('by a mapper and a comparator', () => { 90 | const family = Seq([ 91 | { name: 'Oakley', age: 7 }, 92 | { name: 'Dakota', age: 7 }, 93 | { name: 'Casey', age: 34 }, 94 | { name: 'Avery', age: 34 }, 95 | ]); 96 | expect( 97 | family.minBy( 98 | (p) => p.age, 99 | (a, b) => b - a 100 | ) 101 | ).toBe(family.get(2)); 102 | }); 103 | 104 | check.it('is not dependent on order', [genHeterogeneousishArray], (vals) => { 105 | expect(is(Seq(shuffle(vals.slice())).min(), Seq(vals).min())).toEqual(true); 106 | }); 107 | }); 108 | 109 | function shuffle(array) { 110 | let m = array.length; 111 | let t; 112 | let i; 113 | 114 | // While there remain elements to shuffle… 115 | while (m) { 116 | // Pick a remaining element… 117 | i = Math.floor(Math.random() * m--); 118 | 119 | // And swap it with the current element. 120 | t = array[m]; 121 | array[m] = array[i]; 122 | array[i] = t; 123 | } 124 | 125 | return array; 126 | } 127 | -------------------------------------------------------------------------------- /__tests__/sort.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import { List, OrderedMap, Range, Seq } from 'immutable'; 11 | 12 | describe('sort', () => { 13 | it('sorts a sequence', () => { 14 | expect(Seq([4, 5, 6, 3, 2, 1]).sort().toArray()).toEqual([ 15 | 1, 16 | 2, 17 | 3, 18 | 4, 19 | 5, 20 | 6, 21 | ]); 22 | }); 23 | 24 | it('sorts a list', () => { 25 | expect(List([4, 5, 6, 3, 2, 1]).sort().toArray()).toEqual([ 26 | 1, 27 | 2, 28 | 3, 29 | 4, 30 | 5, 31 | 6, 32 | ]); 33 | }); 34 | 35 | it('sorts undefined values last', () => { 36 | expect( 37 | List([4, undefined, 5, 6, 3, undefined, 2, 1]).sort().toArray() 38 | ).toEqual([1, 2, 3, 4, 5, 6, undefined, undefined]); 39 | }); 40 | 41 | it('sorts a keyed sequence', () => { 42 | expect( 43 | Seq({ z: 1, y: 2, x: 3, c: 3, b: 2, a: 1 }).sort().entrySeq().toArray() 44 | ).toEqual([ 45 | ['z', 1], 46 | ['a', 1], 47 | ['y', 2], 48 | ['b', 2], 49 | ['x', 3], 50 | ['c', 3], 51 | ]); 52 | }); 53 | 54 | it('sorts an OrderedMap', () => { 55 | expect( 56 | OrderedMap({ z: 1, y: 2, x: 3, c: 3, b: 2, a: 1 }) 57 | .sort() 58 | .entrySeq() 59 | .toArray() 60 | ).toEqual([ 61 | ['z', 1], 62 | ['a', 1], 63 | ['y', 2], 64 | ['b', 2], 65 | ['x', 3], 66 | ['c', 3], 67 | ]); 68 | }); 69 | 70 | it('accepts a sort function', () => { 71 | expect( 72 | Seq([4, 5, 6, 3, 2, 1]) 73 | .sort((a, b) => b - a) 74 | .toArray() 75 | ).toEqual([6, 5, 4, 3, 2, 1]); 76 | }); 77 | 78 | it('sorts by using a mapper', () => { 79 | expect( 80 | Range(1, 10) 81 | .sortBy((v) => v % 3) 82 | .toArray() 83 | ).toEqual([3, 6, 9, 1, 4, 7, 2, 5, 8]); 84 | }); 85 | 86 | it('sorts by using a mapper and a sort function', () => { 87 | expect( 88 | Range(1, 10) 89 | .sortBy( 90 | (v) => v % 3, 91 | (a: number, b: number) => b - a 92 | ) 93 | .toArray() 94 | ).toEqual([2, 5, 8, 1, 4, 7, 3, 6, 9]); 95 | }); 96 | }); 97 | -------------------------------------------------------------------------------- /__tests__/splice.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import * as jasmineCheck from 'jasmine-check'; 11 | jasmineCheck.install(); 12 | 13 | import { List, Range, Seq } from 'immutable'; 14 | 15 | describe('splice', () => { 16 | it('splices a sequence only removing elements', () => { 17 | expect(Seq([1, 2, 3]).splice(0, 1).toArray()).toEqual([2, 3]); 18 | expect(Seq([1, 2, 3]).splice(1, 1).toArray()).toEqual([1, 3]); 19 | expect(Seq([1, 2, 3]).splice(2, 1).toArray()).toEqual([1, 2]); 20 | expect(Seq([1, 2, 3]).splice(3, 1).toArray()).toEqual([1, 2, 3]); 21 | }); 22 | 23 | it('splices a list only removing elements', () => { 24 | expect(List([1, 2, 3]).splice(0, 1).toArray()).toEqual([2, 3]); 25 | expect(List([1, 2, 3]).splice(1, 1).toArray()).toEqual([1, 3]); 26 | expect(List([1, 2, 3]).splice(2, 1).toArray()).toEqual([1, 2]); 27 | expect(List([1, 2, 3]).splice(3, 1).toArray()).toEqual([1, 2, 3]); 28 | }); 29 | 30 | it('splicing by infinity', () => { 31 | const l = List(['a', 'b', 'c', 'd']); 32 | expect(l.splice(2, Infinity, 'x').toArray()).toEqual(['a', 'b', 'x']); 33 | expect(l.splice(Infinity, 2, 'x').toArray()).toEqual([ 34 | 'a', 35 | 'b', 36 | 'c', 37 | 'd', 38 | 'x', 39 | ]); 40 | 41 | const s = List(['a', 'b', 'c', 'd']); 42 | expect(s.splice(2, Infinity, 'x').toArray()).toEqual(['a', 'b', 'x']); 43 | expect(s.splice(Infinity, 2, 'x').toArray()).toEqual([ 44 | 'a', 45 | 'b', 46 | 'c', 47 | 'd', 48 | 'x', 49 | ]); 50 | }); 51 | 52 | it('has the same behavior as array splice in known edge cases', () => { 53 | // arbitrary numbers that sum to 31 54 | const a = Range(0, 49).toArray(); 55 | const v = List(a); 56 | a.splice(-18, 0, 0); 57 | expect(v.splice(-18, 0, 0).toList().toArray()).toEqual(a); 58 | }); 59 | 60 | check.it( 61 | 'has the same behavior as array splice', 62 | [gen.array(gen.int), gen.array(gen.oneOf([gen.int, gen.undefined]))], 63 | (values, args) => { 64 | const v = List(values); 65 | const a = values.slice(); // clone 66 | const splicedV = v.splice.apply(v, args); // persistent 67 | a.splice.apply(a, args); // mutative 68 | expect(splicedV.toArray()).toEqual(a); 69 | } 70 | ); 71 | }); 72 | -------------------------------------------------------------------------------- /__tests__/transformerProtocol.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /// 9 | 10 | import * as jasmineCheck from 'jasmine-check'; 11 | import * as t from 'transducers-js'; 12 | jasmineCheck.install(); 13 | 14 | import { List, Map, Set, Stack } from 'immutable'; 15 | 16 | describe('Transformer Protocol', () => { 17 | it('transduces Stack without initial values', () => { 18 | const s = Stack.of(1, 2, 3, 4); 19 | const xform = t.comp( 20 | t.filter((x) => x % 2 === 0), 21 | t.map((x) => x + 1) 22 | ); 23 | const s2 = t.transduce(xform, Stack(), s); 24 | expect(s.toArray()).toEqual([1, 2, 3, 4]); 25 | expect(s2.toArray()).toEqual([5, 3]); 26 | }); 27 | 28 | it('transduces Stack with initial values', () => { 29 | const v1 = Stack.of(1, 2, 3); 30 | const v2 = Stack.of(4, 5, 6, 7); 31 | const xform = t.comp( 32 | t.filter((x) => x % 2 === 0), 33 | t.map((x) => x + 1) 34 | ); 35 | const r = t.transduce(xform, Stack(), v1, v2); 36 | expect(v1.toArray()).toEqual([1, 2, 3]); 37 | expect(v2.toArray()).toEqual([4, 5, 6, 7]); 38 | expect(r.toArray()).toEqual([7, 5, 1, 2, 3]); 39 | }); 40 | 41 | it('transduces List without initial values', () => { 42 | const v = List.of(1, 2, 3, 4); 43 | const xform = t.comp( 44 | t.filter((x) => x % 2 === 0), 45 | t.map((x) => x + 1) 46 | ); 47 | const r = t.transduce(xform, List(), v); 48 | expect(v.toArray()).toEqual([1, 2, 3, 4]); 49 | expect(r.toArray()).toEqual([3, 5]); 50 | }); 51 | 52 | it('transduces List with initial values', () => { 53 | const v1 = List.of(1, 2, 3); 54 | const v2 = List.of(4, 5, 6, 7); 55 | const xform = t.comp( 56 | t.filter((x) => x % 2 === 0), 57 | t.map((x) => x + 1) 58 | ); 59 | const r = t.transduce(xform, List(), v1, v2); 60 | expect(v1.toArray()).toEqual([1, 2, 3]); 61 | expect(v2.toArray()).toEqual([4, 5, 6, 7]); 62 | expect(r.toArray()).toEqual([1, 2, 3, 5, 7]); 63 | }); 64 | 65 | it('transduces Map without initial values', () => { 66 | const m1 = Map({ a: 1, b: 2, c: 3, d: 4 }); 67 | const xform = t.comp( 68 | t.filter(([k, v]) => v % 2 === 0), 69 | t.map(([k, v]) => [k, v * 2]) 70 | ); 71 | const m2 = t.transduce(xform, Map(), m1); 72 | expect(m1.toObject()).toEqual({ a: 1, b: 2, c: 3, d: 4 }); 73 | expect(m2.toObject()).toEqual({ b: 4, d: 8 }); 74 | }); 75 | 76 | it('transduces Map with initial values', () => { 77 | const m1 = Map({ a: 1, b: 2, c: 3 }); 78 | const m2 = Map({ a: 4, b: 5 }); 79 | const xform = t.comp( 80 | t.filter(([k, v]) => v % 2 === 0), 81 | t.map(([k, v]) => [k, v * 2]) 82 | ); 83 | const m3 = t.transduce(xform, Map(), m1, m2); 84 | expect(m1.toObject()).toEqual({ a: 1, b: 2, c: 3 }); 85 | expect(m2.toObject()).toEqual({ a: 4, b: 5 }); 86 | expect(m3.toObject()).toEqual({ a: 8, b: 2, c: 3 }); 87 | }); 88 | 89 | it('transduces Set without initial values', () => { 90 | const s1 = Set.of(1, 2, 3, 4); 91 | const xform = t.comp( 92 | t.filter((x) => x % 2 === 0), 93 | t.map((x) => x + 1) 94 | ); 95 | const s2 = t.transduce(xform, Set(), s1); 96 | expect(s1.toArray()).toEqual([1, 2, 3, 4]); 97 | expect(s2.toArray()).toEqual([3, 5]); 98 | }); 99 | 100 | it('transduces Set with initial values', () => { 101 | const s1 = Set.of(1, 2, 3, 4); 102 | const s2 = Set.of(2, 3, 4, 5, 6); 103 | const xform = t.comp( 104 | t.filter((x) => x % 2 === 0), 105 | t.map((x) => x + 1) 106 | ); 107 | const s3 = t.transduce(xform, Set(), s1, s2); 108 | expect(s1.toArray()).toEqual([1, 2, 3, 4]); 109 | expect(s2.toArray()).toEqual([2, 3, 4, 5, 6]); 110 | expect(s3.toArray()).toEqual([1, 2, 3, 4, 5, 7]); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /__tests__/utils.js: -------------------------------------------------------------------------------- 1 | /* global document */ 2 | const { List, isPlainObject } = require('../src/Immutable'); 3 | 4 | describe('Utils', () => { 5 | describe('isPlainObj()', function testFunc() { 6 | const nonPlainCases = [ 7 | ['Host object', document.createElement('div')], 8 | ['bool primitive false', false], 9 | ['bool primitive true', true], 10 | ['falsy undefined', undefined], 11 | ['falsy null', null], 12 | ['Simple function', function () {}], 13 | [ 14 | 'Instance of other object', 15 | (function () { 16 | function Foo() {} 17 | return new Foo(); 18 | })(), 19 | ], 20 | ['Number primitive ', 5], 21 | ['String primitive ', 'P'], 22 | ['Number Object', Number(6)], 23 | ['Immutable.List', new List()], 24 | ['simple array', ['one']], 25 | ['Error', Error], 26 | ['Internal namespaces', Math], 27 | ['Arguments', arguments], 28 | ]; 29 | const plainCases = [ 30 | ['literal Object', {}], 31 | ['new Object', new Object()], // eslint-disable-line no-new-object 32 | ['Object.create(null)', Object.create(null)], 33 | ['nested object', { one: { prop: 'two' } }], 34 | ['constructor prop', { constructor: 'prop' }], // shadows an object's constructor 35 | ['constructor.name', { constructor: { name: 'two' } }], // shadows an object's constructor.name 36 | [ 37 | 'Fake toString', 38 | { 39 | toString: function () { 40 | return '[object Object]'; 41 | }, 42 | }, 43 | ], 44 | ]; 45 | 46 | nonPlainCases.forEach(([name, value]) => { 47 | it(`${name} returns false`, () => { 48 | expect(isPlainObject(value)).toBe(false); 49 | }); 50 | }); 51 | 52 | plainCases.forEach(([name, value]) => { 53 | it(`${name} returns true`, () => { 54 | expect(isPlainObject(value)).toBe(true); 55 | }); 56 | }); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /pages/.babelrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["@babel/preset-env", { "targets": "> 0.25%, not dead" }], 4 | "@babel/preset-react" 5 | ], 6 | "plugins": ["@babel/plugin-proposal-class-properties"] 7 | } 8 | -------------------------------------------------------------------------------- /pages/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true 4 | }, 5 | "parser": "@babel/eslint-parser", 6 | "extends": "../.eslintrc.json", 7 | "rules": { 8 | "react/static-property-placement": "off", 9 | "react/forbid-prop-types": "off", 10 | "react/require-default-props": "off", 11 | "camelcase": ["error", { "allow": ["^UNSAFE_"] }] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /pages/lib/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true 4 | }, 5 | "extends": "../../.eslintrc.json" 6 | } 7 | -------------------------------------------------------------------------------- /pages/lib/TypeKind.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const TypeKind = { 9 | Any: 0, 10 | 11 | Boolean: 1, 12 | Number: 2, 13 | String: 3, 14 | Object: 4, 15 | Array: 5, 16 | Never: 6, 17 | Function: 7, 18 | 19 | Param: 8, 20 | Type: 9, 21 | 22 | This: 10, 23 | Undefined: 11, 24 | Null: 12, 25 | Union: 13, 26 | Intersection: 14, 27 | Tuple: 15, 28 | Indexed: 16, 29 | Operator: 17, 30 | 31 | Unknown: 18, 32 | }; 33 | 34 | module.exports = TypeKind; 35 | -------------------------------------------------------------------------------- /pages/lib/collectMemberGroups.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const { Seq } = require('../../dist/immutable'); 9 | // Note: intentionally using raw defs, not getTypeDefs to avoid circular ref. 10 | 11 | function collectMemberGroups(interfaceDef, options, defs) { 12 | const members = {}; 13 | 14 | function collectFromDef(def, name) { 15 | def.groups && 16 | def.groups.forEach((g) => { 17 | Seq(g.members).forEach((memberDef, memberName) => { 18 | collectMember(g.title || '', memberName, memberDef); 19 | }); 20 | }); 21 | 22 | def.extends && 23 | def.extends.forEach((e) => { 24 | let superModule = defs.Immutable; 25 | e.name.split('.').forEach((part) => { 26 | superModule = 27 | superModule && superModule.module && superModule.module[part]; 28 | }); 29 | const superInterface = superModule && superModule.interface; 30 | if (superInterface) { 31 | collectFromDef(superInterface, e.name); 32 | } 33 | }); 34 | 35 | function collectMember(group, memberName, memberDef) { 36 | let member = members[memberName]; 37 | if (member) { 38 | if (!member.inherited) { 39 | member.overrides = { name, def, memberDef }; 40 | } 41 | if (!member.group && group) { 42 | member.group = group; 43 | } 44 | } else { 45 | member = { 46 | group, 47 | memberName: memberName.substr(1), 48 | memberDef, 49 | }; 50 | if (def !== interfaceDef) { 51 | member.inherited = { name, def }; 52 | } 53 | members[memberName] = member; 54 | } 55 | } 56 | } 57 | 58 | if (interfaceDef) { 59 | collectFromDef(interfaceDef); 60 | } 61 | 62 | let groups = { '': [] }; 63 | 64 | if (options.showInGroups) { 65 | Seq(members).forEach((member) => { 66 | (groups[member.group] || (groups[member.group] = [])).push(member); 67 | }); 68 | } else { 69 | groups[''] = Seq(members) 70 | .toIndexedSeq() 71 | .sortBy((member) => member.memberName) 72 | .toArray(); 73 | } 74 | 75 | if (!options.showInherited) { 76 | groups = Seq(groups) 77 | .map((members) => members.filter((member) => !member.inherited)) 78 | .toObject(); 79 | } 80 | 81 | return groups; 82 | } 83 | 84 | module.exports = collectMemberGroups; 85 | -------------------------------------------------------------------------------- /pages/lib/genMarkdownDoc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const markdown = require('./markdown'); 9 | 10 | function genMarkdownDoc(typeDefSource, defs) { 11 | return markdown( 12 | typeDefSource.replace(/\n[^\n]+?travis-ci.org[^\n]+?\n/, '\n'), 13 | { 14 | defs, 15 | typePath: ['Immutable'], 16 | relPath: 'docs/', 17 | }, 18 | defs 19 | ); 20 | } 21 | 22 | module.exports = genMarkdownDoc; 23 | -------------------------------------------------------------------------------- /pages/lib/getTypeDefs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const markdownDocs = require('./markdownDocs'); 9 | const defs = require('../generated/immutable.d.json'); 10 | 11 | markdownDocs(defs); 12 | 13 | module.exports = defs; 14 | -------------------------------------------------------------------------------- /pages/lib/markdownDocs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const { Seq } = require('../../'); 9 | const markdown = require('./markdown'); 10 | 11 | function generate(defs) { 12 | function markdownDocs(defs) { 13 | markdownTypes(defs, []); 14 | 15 | function markdownTypes(typeDefs, path) { 16 | Seq(typeDefs).forEach((typeDef, typeName) => { 17 | const typePath = path.concat(typeName); 18 | markdownDoc(typeDef.doc, { typePath }); 19 | typeDef.call && 20 | markdownDoc(typeDef.call.doc, { 21 | typePath, 22 | signatures: typeDef.call.signatures, 23 | }); 24 | if (typeDef.interface) { 25 | markdownDoc(typeDef.interface.doc, { defs, typePath }); 26 | Seq(typeDef.interface.groups).forEach((group) => 27 | Seq(group.members).forEach((member, memberName) => 28 | markdownDoc(member.doc, { 29 | typePath: typePath.concat(memberName.slice(1)), 30 | signatures: member.signatures, 31 | }) 32 | ) 33 | ); 34 | } 35 | typeDef.module && markdownTypes(typeDef.module, typePath); 36 | }); 37 | } 38 | } 39 | 40 | function markdownDoc(doc, context) { 41 | if (!doc) { 42 | return; 43 | } 44 | doc.synopsis && (doc.synopsis = markdown(doc.synopsis, context, defs)); 45 | doc.description && 46 | (doc.description = markdown(doc.description, context, defs)); 47 | doc.notes && 48 | doc.notes.forEach((note) => { 49 | if (note.name !== 'alias') { 50 | note.body = markdown(note.body, context, defs); 51 | } 52 | }); 53 | } 54 | 55 | return markdownDocs(defs); 56 | } 57 | module.exports = generate; 58 | -------------------------------------------------------------------------------- /pages/lib/runkit-embed.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | global.runIt = function runIt(button) { 3 | if (!global.RunKit) return; 4 | 5 | const container = document.createElement('div'); 6 | const codeElement = button.parentNode; 7 | const parent = codeElement.parentNode; 8 | 9 | parent.insertBefore(container, codeElement); 10 | parent.removeChild(codeElement); 11 | codeElement.removeChild(button); 12 | 13 | const options = JSON.parse(unescape(button.dataset.options)); 14 | 15 | function withCorrectVersion(code) { 16 | return code.replace( 17 | /require\('immutable'\)/g, 18 | "require('immutable@4.0.0-rc.9')" 19 | ); 20 | } 21 | 22 | global.RunKit.createNotebook({ 23 | element: container, 24 | nodeVersion: options.nodeVersion || '*', 25 | preamble: withCorrectVersion( 26 | 'const assert = (' + 27 | makeAssert + 28 | ")(require('immutable'));" + 29 | (options.preamble || '') 30 | ), 31 | source: withCorrectVersion( 32 | codeElement.textContent.replace(/\n(>[^\n]*\n?)+$/g, '') 33 | ), 34 | minHeight: '52px', 35 | onLoad: function (notebook) { 36 | notebook.evaluate(); 37 | }, 38 | }); 39 | }; 40 | 41 | function makeAssert(I) { 42 | const isIterable = I.isIterable || I.Iterable.isIterable; 43 | let html = ` 44 | `; 80 | 81 | function compare(lhs, rhs, same, identical) { 82 | const both = !identical && isIterable(lhs) && isIterable(rhs); 83 | 84 | if (both) return lhs.equals(rhs); 85 | 86 | return lhs === rhs; 87 | } 88 | 89 | function message(lhs, rhs, same, identical) { 90 | const result = compare(lhs, rhs, same, identical); 91 | const comparison = result 92 | ? identical 93 | ? 'strict equal to' 94 | : 'does equal' 95 | : identical 96 | ? 'not strict equal to' 97 | : 'does not equal'; 98 | const className = result === same ? 'success' : 'failure'; 99 | const lhsString = isIterable(lhs) ? lhs + '' : JSON.stringify(lhs); 100 | const rhsString = isIterable(rhs) ? rhs + '' : JSON.stringify(rhs); 101 | 102 | return (html += ` 103 | 104 | ${lhsString} 105 | ${comparison} 106 | ${rhsString} 107 |
`); 108 | } 109 | 110 | function equal(lhs, rhs) { 111 | return message(lhs, rhs, true); 112 | } 113 | 114 | function notEqual(lhs, rhs) { 115 | return message(lhs, rhs, false); 116 | } 117 | 118 | function strictEqual(lhs, rhs) { 119 | return message(lhs, rhs, true, true); 120 | } 121 | 122 | function notStrictEqual(lhs, rhs) { 123 | return message(lhs, rhs, false, true); 124 | } 125 | 126 | return { equal, notEqual, strictEqual, notStrictEqual }; 127 | } 128 | -------------------------------------------------------------------------------- /pages/src/docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Immutable.js 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /pages/src/docs/src/DocHeader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | 10 | import SVGSet from '../../src/SVGSet'; 11 | import Logo from '../../src/Logo'; 12 | import getGlobalData from './global'; 13 | 14 | function DocHeader() { 15 | return ( 16 | 36 | ); 37 | } 38 | 39 | export default DocHeader; 40 | -------------------------------------------------------------------------------- /pages/src/docs/src/DocOverview.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React, { Component } from 'react'; 9 | import { Link } from 'react-router-dom'; 10 | import { Seq } from '../../../../'; 11 | import Markdown from './MarkDown'; 12 | import PropTypes from 'prop-types'; 13 | 14 | class DocOverview extends Component { 15 | static propTypes = { 16 | def: PropTypes.object.isRequired, 17 | }; 18 | 19 | render() { 20 | const def = this.props.def; 21 | const doc = def.doc; 22 | 23 | return ( 24 |
25 | {doc && ( 26 |
27 | 28 | {doc.description && } 29 |
30 | )} 31 | 32 |

API

33 | 34 | {Seq(def.module) 35 | .map((t, name) => { 36 | const isFunction = !t.interface && !t.module; 37 | if (isFunction) { 38 | t = t.call; 39 | } 40 | const anchorLink = `/${name}`; 41 | return ( 42 |
43 |

44 | {name + (isFunction ? '()' : '')} 45 |

46 | {t.doc && ( 47 | 48 | )} 49 |
50 | ); 51 | }) 52 | .valueSeq() 53 | .toArray()} 54 |
55 | ); 56 | } 57 | } 58 | 59 | export default DocOverview; 60 | -------------------------------------------------------------------------------- /pages/src/docs/src/DocSearch.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | class DocSearch extends Component { 4 | constructor(props, ...args) { 5 | super(props, ...args); 6 | this.state = { 7 | enabled: true, 8 | }; 9 | } 10 | 11 | componentDidMount() { 12 | const script = document.createElement('script'); 13 | const firstScript = document.getElementsByTagName('script')[0]; 14 | script.src = 15 | 'https://cdn.jsdelivr.net/npm/docsearch.js@2.5.2/dist/cdn/docsearch.min.js'; 16 | script.addEventListener( 17 | 'load', 18 | () => { 19 | // Initialize Algolia search - unless we are pre-rendering. 20 | if (typeof document !== 'undefined' && window.docsearch) { 21 | window.docsearch({ 22 | apiKey: '83f61f865ef4cb682e0432410c2f7809', 23 | indexName: 'immutable_js', 24 | inputSelector: '#algolia-docsearch', 25 | }); 26 | } else { 27 | this.setState({ enabled: false }); 28 | } 29 | }, 30 | false 31 | ); 32 | firstScript.parentNode.insertBefore(script, firstScript); 33 | 34 | const link = document.createElement('link'); 35 | const firstLink = document.getElementsByTagName('link')[0]; 36 | link.rel = 'stylesheet'; 37 | link.href = 38 | 'https://cdn.jsdelivr.net/npm/docsearch.js@2.5.2/dist/cdn/docsearch.min.css'; 39 | firstLink.parentNode.insertBefore(link, firstLink); 40 | } 41 | 42 | render() { 43 | return this.state.enabled ? ( 44 | 50 | ) : null; 51 | } 52 | } 53 | 54 | export default DocSearch; 55 | -------------------------------------------------------------------------------- /pages/src/docs/src/MarkDown.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React, { Component } from 'react'; 9 | import PropTypes from 'prop-types'; 10 | 11 | export default class MarkDown extends Component { 12 | static propTypes = { 13 | contents: PropTypes.oneOfType([PropTypes.string, PropTypes.node]) 14 | .isRequired, 15 | className: PropTypes.string, 16 | }; 17 | 18 | shouldComponentUpdate() { 19 | return false; 20 | } 21 | 22 | render() { 23 | const html = this.props.contents; 24 | return ( 25 |
29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /pages/src/docs/src/bundle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This source code is licensed under the MIT license found in the 3 | * LICENSE file in the root directory of this source tree. 4 | */ 5 | 6 | import React from 'react'; 7 | import { render } from 'react-dom'; 8 | import { HashRouter as Router } from 'react-router-dom'; 9 | import App from './index'; 10 | 11 | if ('scrollRestoration' in window.history) { 12 | // prevent the browser from tampering with our scroll state 13 | window.history.scrollRestoration = 'manual'; 14 | } 15 | 16 | // We could use React's hydrate here. But the paths of StaticRouter match BrowserRouter, but not HashRouter, so we might end up with wrong links 17 | render( 18 | 19 | 20 | , 21 | document.querySelector('#app') 22 | ); 23 | -------------------------------------------------------------------------------- /pages/src/docs/src/components/Disclaimer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import constants from '../constants'; 3 | 4 | export default function Disclaimer() { 5 | return ( 6 |
7 | This documentation is generated from{' '} 8 | Immutable.d.ts. Pull requests and{' '} 9 | Issues welcome. 10 |
11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /pages/src/docs/src/components/FunctionDoc.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import MarkDown from '../MarkDown'; 4 | import { CallSigDef } from '../Defs'; 5 | import Disclaimer from './Disclaimer'; 6 | 7 | export default class FunctionDoc extends Component { 8 | static propTypes = { 9 | name: PropTypes.string.isRequired, 10 | def: PropTypes.object.isRequired, 11 | }; 12 | 13 | render() { 14 | const name = this.props.name; 15 | const def = this.props.def; 16 | const doc = def.doc || {}; 17 | 18 | return ( 19 |
20 |

{name + '()'}

21 | {doc.synopsis && ( 22 | 23 | )} 24 | 25 | {def.signatures.map((callSig, i) => [ 26 | , 27 | '\n', 28 | ])} 29 | 30 | {doc.notes && 31 | doc.notes.map((note, i) => ( 32 |
33 |

{note.name}

34 | {note.name === 'alias' ? ( 35 | 36 | ) : ( 37 | note.body 38 | )} 39 |
40 | ))} 41 | {doc.description && ( 42 |
43 |

44 | {doc.description.substr(0, 5) === ' 48 | 49 |

50 | )} 51 | 52 |
53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /pages/src/docs/src/constants.js: -------------------------------------------------------------------------------- 1 | export default { 2 | typeDefURL: 3 | 'https://github.com/immutable-js-oss/immutable-js/blob/master/type-definitions/Immutable.d.ts', 4 | issuesURL: 'https://github.com/immutable-js-oss/immutable-js/issues', 5 | }; 6 | -------------------------------------------------------------------------------- /pages/src/docs/src/global.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This source code is licensed under the MIT license found in the 3 | * LICENSE file in the root directory of this source tree. 4 | */ 5 | 6 | export default function getGlobalData() { 7 | if (typeof document === 'undefined') { 8 | // pre-rendering, injected by gulp 9 | return global.data; 10 | } 11 | return window.data; 12 | } 13 | -------------------------------------------------------------------------------- /pages/src/docs/src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | import { Route, Switch } from 'react-router-dom'; 10 | import DocHeader from './DocHeader'; 11 | import DocSearch from './DocSearch'; 12 | import TypeDocumentation from './TypeDocumentation'; 13 | 14 | import '../../../lib/runkit-embed'; 15 | 16 | function App() { 17 | return ( 18 |
19 | 20 |
21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 |
31 | ); 32 | } 33 | 34 | export default App; 35 | -------------------------------------------------------------------------------- /pages/src/docs/src/isMobile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // TODO useless, always false 9 | function isMobileMatch() { 10 | if (typeof window === 'undefined') { 11 | return false; 12 | } 13 | if (!window.matchMedia) { 14 | return false; 15 | } 16 | return window.matchMedia('(max-device-width: 680px)').matches; 17 | } 18 | 19 | export default !!isMobileMatch(); 20 | -------------------------------------------------------------------------------- /pages/src/docs/src/server.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This source code is licensed under the MIT license found in the 3 | * LICENSE file in the root directory of this source tree. 4 | */ 5 | 6 | import React from 'react'; 7 | import { StaticRouter as Router } from 'react-router-dom'; 8 | import { renderToString } from 'react-dom/server'; 9 | import App from './index'; 10 | 11 | // This is used by the gulp pre-rendering process to generate a static version of the docs, which search engines can crawl. 12 | // global.output is picked up by vm.runInNewContext 13 | const content = renderToString( 14 | 15 | 16 | 17 | ); 18 | global.output = content; 19 | -------------------------------------------------------------------------------- /pages/src/docs/version.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Immutable.js <!--version--> 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /pages/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Immutable.js 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /pages/src/src/SVGSet.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | import PropTypes from 'prop-types'; 10 | 11 | function SVGSet(props) { 12 | return ( 13 | 14 | {props.children} 15 | 16 | ); 17 | } 18 | 19 | SVGSet.propTypes = { 20 | style: PropTypes.object, 21 | }; 22 | 23 | export default SVGSet; 24 | -------------------------------------------------------------------------------- /pages/src/src/StarBtn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React, { Component } from 'react'; 9 | import loadJSON from './loadJSON'; 10 | 11 | // API endpoints 12 | // https://registry.npmjs.org/immutable/latest 13 | // https://api.github.com/repos/facebook/immutable-js 14 | 15 | class StarBtn extends Component { 16 | constructor(props, ...args) { 17 | super(props, ...args); 18 | this.state = { 19 | stars: null, 20 | }; 21 | } 22 | 23 | componentDidMount() { 24 | loadJSON('https://api.github.com/repos/facebook/immutable-js', (value) => { 25 | value && 26 | value.stargazers_count && 27 | this.setState({ stars: value.stargazers_count }); 28 | }); 29 | } 30 | 31 | render() { 32 | return ( 33 | 34 | 39 | 40 | Star 41 | 42 | {this.state.stars && } 43 | {this.state.stars && ( 44 | 48 | {this.state.stars} 49 | 50 | )} 51 | 52 | ); 53 | } 54 | } 55 | 56 | export default StarBtn; 57 | -------------------------------------------------------------------------------- /pages/src/src/base.less: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | @link-color: #4183c4; 9 | @header-color: #212325; 10 | @body-color: #626466; 11 | 12 | html, 13 | body { 14 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 15 | -webkit-text-size-adjust: 100%; 16 | -ms-text-size-adjust: 100%; 17 | margin: 0; 18 | padding: 0; 19 | -webkit-font-smoothing: antialiased; 20 | } 21 | 22 | body, 23 | input { 24 | color: @body-color; 25 | font-family: 'Fira Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; 26 | font-size: 16px; 27 | line-height: 1.625; 28 | } 29 | 30 | @media only screen and (max-width: 680px) { 31 | body, 32 | input { 33 | font-size: 14px; 34 | } 35 | } 36 | 37 | h1, 38 | h2, 39 | h3, 40 | h4, 41 | h5, 42 | h6 { 43 | color: @header-color; 44 | } 45 | 46 | a { 47 | color: @link-color; 48 | text-decoration: none; 49 | } 50 | 51 | pre, 52 | code { 53 | font-family: 'Fira Mono', Menlo, monospace; 54 | background: #f9f8f7; 55 | color: #484a4c; 56 | font-size: 0.9375em; 57 | letter-spacing: -0.015em; 58 | } 59 | 60 | code { 61 | margin: -0.05rem -0.15em; 62 | padding: 0.05rem 0.35em; 63 | } 64 | 65 | blockquote { 66 | margin: 1rem 0; 67 | padding: 0 1rem; 68 | color: #727476; 69 | border-left: solid 3px #dcdad9; 70 | } 71 | 72 | blockquote > :first-child { 73 | margin-top: 0; 74 | } 75 | 76 | blockquote > :last-child { 77 | margin-bottom: 0; 78 | } 79 | 80 | // Markdown 81 | 82 | .codeBlock { 83 | -webkit-overflow-scrolling: touch; 84 | background: #fcfbfa; 85 | border-left: solid 3px #eceae9; 86 | box-sizing: border-box; 87 | display: block; 88 | font-size: 0.875em; 89 | margin: 0.5rem 0; 90 | overflow-y: scroll; 91 | padding: 0.5rem 8px 0.5rem 12px; 92 | white-space: pre; 93 | position: relative; 94 | } 95 | 96 | .t.blockParams { 97 | padding-left: 2ch; 98 | } 99 | 100 | // TODO: not random colors 101 | 102 | .token.punctuation, 103 | .token.ignore, 104 | .t.interfaceDef, 105 | .t.member, 106 | .t.callSig { 107 | color: #808890; 108 | } 109 | 110 | .token.function, 111 | .token.class-name, 112 | .token.qualifier, 113 | .t.fnQualifier, 114 | .t.fnName { 115 | color: #32308e; 116 | } 117 | 118 | .token.primitive, 119 | .t.primitive { 120 | color: #922; 121 | } 122 | 123 | .token.number, 124 | .t.typeParam { 125 | color: #905; 126 | } 127 | 128 | .t.typeQualifier, 129 | .t.typeName { 130 | color: #013679; 131 | } 132 | 133 | .t.param { 134 | color: #945277; 135 | } 136 | 137 | .t.memberName { 138 | color: teal; 139 | } 140 | 141 | .token.block-keyword, 142 | .token.keyword, 143 | .t.keyword { 144 | color: #a51; 145 | } 146 | 147 | .token.string, 148 | .token.regex { 149 | color: #df5050; 150 | } 151 | 152 | .token.operator { 153 | color: #a67f59; 154 | } 155 | 156 | .token.comment { 157 | color: #998; 158 | font-style: italic; 159 | } 160 | 161 | a.try-it { 162 | position: absolute; 163 | cursor: pointer; 164 | right: 1em; 165 | border: 0; 166 | background: transparent; 167 | border-bottom: 2px solid rgba(49, 50, 137, 0.2); 168 | color: rgba(49, 50, 137, 1); 169 | } 170 | -------------------------------------------------------------------------------- /pages/src/src/bundle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This source code is licensed under the MIT license found in the 3 | * LICENSE file in the root directory of this source tree. 4 | */ 5 | 6 | import React from 'react'; 7 | import { hydrate } from 'react-dom'; 8 | 9 | /* 10 | window.data = { 11 | Immutable: window.Immutable 12 | }; 13 | */ 14 | 15 | import App from './index'; 16 | 17 | hydrate(, document.querySelector('#app')); 18 | -------------------------------------------------------------------------------- /pages/src/src/global.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This source code is licensed under the MIT license found in the 3 | * LICENSE file in the root directory of this source tree. 4 | */ 5 | 6 | export default function getGlobalData() { 7 | if (typeof document === 'undefined') { 8 | // pre-rendering, injected by gulp 9 | return global.data; 10 | } 11 | return window.data; 12 | } 13 | -------------------------------------------------------------------------------- /pages/src/src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react'; 9 | import Header from './Header'; 10 | import readme from '../../generated/readme.json'; 11 | import '../../lib/runkit-embed'; 12 | 13 | function Index() { 14 | return ( 15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | ); 24 | } 25 | 26 | export default Index; 27 | -------------------------------------------------------------------------------- /pages/src/src/loadJSON.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | module.exports = loadJSON; 9 | 10 | function loadJSON(url, then) { 11 | const oReq = new XMLHttpRequest(); 12 | oReq.onload = (event) => { 13 | let json; 14 | try { 15 | json = JSON.parse(event.target.responseText); 16 | } catch (e) { 17 | // ignore error 18 | } 19 | then(json); 20 | }; 21 | oReq.open('get', url, true); 22 | oReq.send(); 23 | } 24 | -------------------------------------------------------------------------------- /pages/src/src/server.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This source code is licensed under the MIT license found in the 3 | * LICENSE file in the root directory of this source tree. 4 | */ 5 | 6 | import React from 'react'; 7 | import { StaticRouter as Router } from 'react-router-dom'; 8 | import { renderToString } from 'react-dom/server'; 9 | import App from './index'; 10 | 11 | // This is used by the gulp pre-rendering process to generate a static version of the docs, which search engines can crawl. 12 | // global.output is picked up by vm.runInNewContext 13 | const content = renderToString( 14 | 15 | 16 | 17 | ); 18 | global.output = content; 19 | -------------------------------------------------------------------------------- /pages/src/src/style.less: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | .header { 9 | -khtml-user-select: none; 10 | -moz-user-select: none; 11 | -ms-user-select: none; 12 | -webkit-touch-callout: none; 13 | -webkit-user-select: none; 14 | user-select: none; 15 | } 16 | 17 | .pageBody { 18 | padding: 0 36px; 19 | position: relative; 20 | } 21 | 22 | .contents { 23 | margin: 0 auto; 24 | max-width: 740px; 25 | padding: 64px 0; 26 | } 27 | 28 | .contents h2 { 29 | margin: 4rem 0 1rem; 30 | } 31 | 32 | .contents h3 { 33 | margin: 2rem 0 1rem; 34 | } 35 | 36 | .miniHeader { 37 | background: #6dbcdb; 38 | position: fixed; 39 | width: 100%; 40 | z-index: 1; 41 | } 42 | 43 | .miniHeaderContents { 44 | margin: 0 auto; 45 | max-width: 880px; 46 | padding: 12px 36px; 47 | text-align: right; 48 | } 49 | 50 | @media only screen and (max-width: 680px) { 51 | .miniHeaderContents { 52 | text-align: left; 53 | } 54 | } 55 | 56 | .miniLogo { 57 | float: left; 58 | left: -140px; 59 | top: 12px; 60 | } 61 | 62 | @media only screen and (max-width: 680px) { 63 | .miniLogo { 64 | display: none; 65 | } 66 | } 67 | 68 | .miniLogo > .svg { 69 | height: 24px; 70 | } 71 | 72 | .miniHeaderContents a { 73 | color: #fff; 74 | font-weight: bold; 75 | margin-right: 1em; 76 | text-decoration: none; 77 | text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35); 78 | } 79 | 80 | .miniHeaderContents a:last-child { 81 | margin-right: 0; 82 | } 83 | 84 | .coverContainer { 85 | background-color: #c1c6c8; 86 | height: 70vh; 87 | max-height: 800px; 88 | min-height: 260px; 89 | outline: solid 1px rgba(0, 0, 0, 0.28); 90 | overflow: hidden; 91 | position: relative; 92 | width: 100%; 93 | z-index: 1; 94 | } 95 | 96 | .cover { 97 | height: 70vh; 98 | max-height: 800px; 99 | min-height: 260px; 100 | position: absolute; 101 | width: 100%; 102 | clip: rect(0, auto, auto, 0); 103 | } 104 | 105 | .coverFixed { 106 | -webkit-align-items: center; 107 | -webkit-flex-direction: column; 108 | -webkit-justify-content: center; 109 | align-items: center; 110 | display: -webkit-flex; 111 | display: flex; 112 | flex-direction: column; 113 | height: 100%; 114 | justify-content: center; 115 | position: fixed; 116 | width: 100%; 117 | top: 0; 118 | height: 70vh; 119 | max-height: 800px; 120 | } 121 | 122 | .filler { 123 | -webkit-flex: 10; 124 | flex: 10; 125 | width: 100%; 126 | } 127 | 128 | .synopsis { 129 | -webkit-flex: 10; 130 | box-sizing: border-box; 131 | flex: 10; 132 | max-width: 700px; 133 | padding: 0 30px; 134 | pointer-events: none; 135 | position: relative; 136 | width: 100%; 137 | } 138 | 139 | .logo { 140 | bottom: 0; 141 | left: 60px; 142 | position: absolute; 143 | right: 60px; 144 | top: 0; 145 | } 146 | 147 | .logo > .svg { 148 | height: 100%; 149 | position: absolute; 150 | width: 100%; 151 | } 152 | 153 | .buttons { 154 | -webkit-align-items: center; 155 | -webkit-flex: 10; 156 | align-items: center; 157 | display: -webkit-flex; 158 | display: flex; 159 | flex: 10; 160 | } 161 | 162 | @media only screen and (max-width: 680px) { 163 | .coverContainer { 164 | max-height: 40vh; 165 | } 166 | 167 | .cover { 168 | max-height: 260px; 169 | } 170 | 171 | .coverFixed { 172 | max-height: 260px; 173 | } 174 | 175 | .miniHeader { 176 | display: none; 177 | } 178 | 179 | .miniHeaderContents { 180 | padding: 12px; 181 | text-align: center; 182 | } 183 | 184 | .synopsis { 185 | max-width: 540px; 186 | } 187 | 188 | .logo { 189 | left: 30px; 190 | right: 30px; 191 | } 192 | 193 | .contents { 194 | padding-top: 24px; 195 | 196 | img { 197 | max-width: 100%; 198 | } 199 | } 200 | 201 | .pageBody { 202 | padding: 0 12px; 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /pages/src/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/immutable-js-oss/immutable-js/43a7c4cd38b557e36a98ebc9f48e97470ef25d64/pages/src/static/favicon.png -------------------------------------------------------------------------------- /perf/List.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | describe('List', function () { 9 | describe('builds from array', function () { 10 | var array2 = []; 11 | for (var ii = 0; ii < 2; ii++) { 12 | array2[ii] = ii; 13 | } 14 | 15 | it('of 2', function () { 16 | Immutable.List(array2); 17 | }); 18 | 19 | var array8 = []; 20 | for (var ii = 0; ii < 8; ii++) { 21 | array8[ii] = ii; 22 | } 23 | 24 | it('of 8', function () { 25 | Immutable.List(array8); 26 | }); 27 | 28 | var array32 = []; 29 | for (var ii = 0; ii < 32; ii++) { 30 | array32[ii] = ii; 31 | } 32 | 33 | it('of 32', function () { 34 | Immutable.List(array32); 35 | }); 36 | 37 | var array1024 = []; 38 | for (var ii = 0; ii < 1024; ii++) { 39 | array1024[ii] = ii; 40 | } 41 | 42 | it('of 1024', function () { 43 | Immutable.List(array1024); 44 | }); 45 | }); 46 | 47 | describe('pushes into', function () { 48 | it('2 times', function () { 49 | var list = Immutable.List(); 50 | for (var ii = 0; ii < 2; ii++) { 51 | list = list.push(ii); 52 | } 53 | }); 54 | 55 | it('8 times', function () { 56 | var list = Immutable.List(); 57 | for (var ii = 0; ii < 8; ii++) { 58 | list = list.push(ii); 59 | } 60 | }); 61 | 62 | it('32 times', function () { 63 | var list = Immutable.List(); 64 | for (var ii = 0; ii < 32; ii++) { 65 | list = list.push(ii); 66 | } 67 | }); 68 | 69 | it('1024 times', function () { 70 | var list = Immutable.List(); 71 | for (var ii = 0; ii < 1024; ii++) { 72 | list = list.push(ii); 73 | } 74 | }); 75 | }); 76 | 77 | describe('pushes into transient', function () { 78 | it('2 times', function () { 79 | var list = Immutable.List().asMutable(); 80 | for (var ii = 0; ii < 2; ii++) { 81 | list = list.push(ii); 82 | } 83 | list = list.asImmutable(); 84 | }); 85 | 86 | it('8 times', function () { 87 | var list = Immutable.List().asMutable(); 88 | for (var ii = 0; ii < 8; ii++) { 89 | list = list.push(ii); 90 | } 91 | list = list.asImmutable(); 92 | }); 93 | 94 | it('32 times', function () { 95 | var list = Immutable.List().asMutable(); 96 | for (var ii = 0; ii < 32; ii++) { 97 | list = list.push(ii); 98 | } 99 | list = list.asImmutable(); 100 | }); 101 | 102 | it('1024 times', function () { 103 | var list = Immutable.List().asMutable(); 104 | for (var ii = 0; ii < 1024; ii++) { 105 | list = list.push(ii); 106 | } 107 | list = list.asImmutable(); 108 | }); 109 | }); 110 | }); 111 | -------------------------------------------------------------------------------- /perf/Map.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | describe('Map', function () { 9 | describe('builds from an object', function () { 10 | var obj2 = {}; 11 | for (var ii = 0; ii < 2; ii++) { 12 | obj2['x' + ii] = ii; 13 | } 14 | 15 | it('of 2', function () { 16 | Immutable.Map(obj2); 17 | }); 18 | 19 | var obj8 = {}; 20 | for (var ii = 0; ii < 8; ii++) { 21 | obj8['x' + ii] = ii; 22 | } 23 | 24 | it('of 8', function () { 25 | Immutable.Map(obj8); 26 | }); 27 | 28 | var obj32 = {}; 29 | for (var ii = 0; ii < 32; ii++) { 30 | obj32['x' + ii] = ii; 31 | } 32 | 33 | it('of 32', function () { 34 | Immutable.Map(obj32); 35 | }); 36 | 37 | var obj1024 = {}; 38 | for (var ii = 0; ii < 1024; ii++) { 39 | obj1024['x' + ii] = ii; 40 | } 41 | 42 | it('of 1024', function () { 43 | Immutable.Map(obj1024); 44 | }); 45 | }); 46 | 47 | describe('builds from an array', function () { 48 | var array2 = []; 49 | for (var ii = 0; ii < 2; ii++) { 50 | array2[ii] = ['x' + ii, ii]; 51 | } 52 | 53 | it('of 2', function () { 54 | Immutable.Map(array2); 55 | }); 56 | 57 | var array8 = []; 58 | for (var ii = 0; ii < 8; ii++) { 59 | array8[ii] = ['x' + ii, ii]; 60 | } 61 | 62 | it('of 8', function () { 63 | Immutable.Map(array8); 64 | }); 65 | 66 | var array32 = []; 67 | for (var ii = 0; ii < 32; ii++) { 68 | array32[ii] = ['x' + ii, ii]; 69 | } 70 | 71 | it('of 32', function () { 72 | Immutable.Map(array32); 73 | }); 74 | 75 | var array1024 = []; 76 | for (var ii = 0; ii < 1024; ii++) { 77 | array1024[ii] = ['x' + ii, ii]; 78 | } 79 | 80 | it('of 1024', function () { 81 | Immutable.Map(array1024); 82 | }); 83 | }); 84 | 85 | describe('builds from a List', function () { 86 | var list2 = Immutable.List().asMutable(); 87 | for (var ii = 0; ii < 2; ii++) { 88 | list2 = list2.push(Immutable.List(['x' + ii, ii])); 89 | } 90 | list2 = list2.asImmutable(); 91 | 92 | it('of 2', function () { 93 | Immutable.Map(list2); 94 | }); 95 | 96 | var list8 = Immutable.List().asMutable(); 97 | for (var ii = 0; ii < 8; ii++) { 98 | list8 = list8.push(Immutable.List(['x' + ii, ii])); 99 | } 100 | list8 = list8.asImmutable(); 101 | 102 | it('of 8', function () { 103 | Immutable.Map(list8); 104 | }); 105 | 106 | var list32 = Immutable.List().asMutable(); 107 | for (var ii = 0; ii < 32; ii++) { 108 | list32 = list32.push(Immutable.List(['x' + ii, ii])); 109 | } 110 | list32 = list32.asImmutable(); 111 | 112 | it('of 32', function () { 113 | Immutable.Map(list32); 114 | }); 115 | 116 | var list1024 = Immutable.List().asMutable(); 117 | for (var ii = 0; ii < 1024; ii++) { 118 | list1024 = list1024.push(Immutable.List(['x' + ii, ii])); 119 | } 120 | list1024 = list1024.asImmutable(); 121 | 122 | it('of 1024', function () { 123 | Immutable.Map(list1024); 124 | }); 125 | }); 126 | 127 | describe('merge a map', () => { 128 | [2, 8, 32, 1024].forEach((size) => { 129 | const obj1 = {}; 130 | const obj2 = {}; 131 | for (let ii = 0; ii < size; ii++) { 132 | obj1['k' + ii] = '1_' + ii; 133 | obj2['k' + ii] = '2_' + ii; 134 | } 135 | 136 | const map1 = Immutable.Map(obj1); 137 | const map2 = Immutable.Map(obj2); 138 | 139 | it('of ' + size, () => { 140 | map1.merge(map2); 141 | }); 142 | }); 143 | }); 144 | }); 145 | -------------------------------------------------------------------------------- /perf/Record.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | describe('Record', () => { 9 | describe('builds from an object', () => { 10 | [2, 5, 10, 100, 1000].forEach((size) => { 11 | var defaults = {}; 12 | var values = {}; 13 | for (var ii = 0; ii < size; ii++) { 14 | defaults['x' + ii] = null; 15 | values['x' + ii] = ii; 16 | } 17 | 18 | var Rec = Immutable.Record(defaults); 19 | 20 | it('of ' + size, () => { 21 | Rec(values); 22 | }); 23 | }); 24 | }); 25 | 26 | describe('update random using set()', () => { 27 | [2, 5, 10, 100, 1000].forEach((size) => { 28 | var defaults = {}; 29 | var values = {}; 30 | for (var ii = 0; ii < size; ii++) { 31 | defaults['x' + ii] = null; 32 | values['x' + ii] = ii; 33 | } 34 | 35 | var Rec = Immutable.Record(defaults); 36 | var rec = Rec(values); 37 | 38 | var key = 'x' + Math.floor(size / 2); 39 | 40 | it('of ' + size, () => { 41 | rec.set(key, 999); 42 | }); 43 | }); 44 | }); 45 | 46 | describe('access random using get()', () => { 47 | [2, 5, 10, 100, 1000].forEach((size) => { 48 | var defaults = {}; 49 | var values = {}; 50 | for (var ii = 0; ii < size; ii++) { 51 | defaults['x' + ii] = null; 52 | values['x' + ii] = ii; 53 | } 54 | 55 | var Rec = Immutable.Record(defaults); 56 | var rec = Rec(values); 57 | 58 | var key = 'x' + Math.floor(size / 2); 59 | 60 | it('of ' + size, () => { 61 | rec.get(key); 62 | }); 63 | }); 64 | }); 65 | 66 | describe('access random using property', () => { 67 | [2, 5, 10, 100, 1000].forEach((size) => { 68 | var defaults = {}; 69 | var values = {}; 70 | for (var ii = 0; ii < size; ii++) { 71 | defaults['x' + ii] = null; 72 | values['x' + ii] = ii; 73 | } 74 | 75 | var Rec = Immutable.Record(defaults); 76 | var rec = Rec(values); 77 | 78 | var key = 'x' + Math.floor(size / 2); 79 | 80 | it('of ' + size, () => { 81 | rec[key]; 82 | }); 83 | }); 84 | }); 85 | }); 86 | -------------------------------------------------------------------------------- /perf/toJS.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | describe('toJS', () => { 9 | const array32 = []; 10 | for (let ii = 0; ii < 32; ii++) { 11 | array32[ii] = ii; 12 | } 13 | const list = Immutable.List(array32); 14 | 15 | it('List of 32', () => { 16 | Immutable.toJS(list); 17 | }); 18 | 19 | const obj32 = {}; 20 | for (let ii = 0; ii < 32; ii++) { 21 | obj32[ii] = ii; 22 | } 23 | const map = Immutable.Map(obj32); 24 | 25 | it('Map of 32', () => { 26 | Immutable.toJS(map); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /resources/COPYRIGHT: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * 4 | * Copyright (c) 2014-present, Facebook, Inc. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | -------------------------------------------------------------------------------- /resources/copy-dist-typedefs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const fs = require('fs'); 9 | const path = require('path'); 10 | 11 | const DIST_DIR = path.resolve('dist'); 12 | const TYPE_DEFS_DIR = path.resolve('type-definitions'); 13 | 14 | const tsTypes = fs.readFileSync( 15 | path.join(TYPE_DEFS_DIR, 'Immutable.d.ts'), 16 | 'utf8' 17 | ); 18 | const flowTypes = fs.readFileSync( 19 | path.join(TYPE_DEFS_DIR, 'immutable.js.flow'), 20 | 'utf8' 21 | ); 22 | 23 | const nonAmbientTsTypes = tsTypes 24 | .replace(/declare\s+module\s+Immutable\s*\{/, '') 25 | .replace( 26 | /\}[\s\n\r]*declare\s+module\s*.'immutable'.[\s\n\r]*{[\s\n\r]*export\s*=\s*Immutable;[\s\n\r]*\}/m, 27 | '' 28 | ); 29 | 30 | fs.writeFileSync(path.join(DIST_DIR, 'immutable.d.ts'), tsTypes, 'utf-8'); 31 | fs.writeFileSync(path.join(DIST_DIR, 'immutable.js.flow'), flowTypes, 'utf-8'); 32 | fs.writeFileSync( 33 | path.join(DIST_DIR, 'immutable-nonambient.d.ts'), 34 | nonAmbientTsTypes, 35 | 'utf-8' 36 | ); 37 | -------------------------------------------------------------------------------- /resources/deploy-ghpages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | # Copyright (c) 2014-present, Facebook, Inc. 4 | # 5 | # This source code is licensed under the MIT license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | # This script maintains the ghpages branch which hosts the immutable.js website 9 | 10 | # Create empty gh-pages directory 11 | rm -rf gh-pages 12 | git clone -b gh-pages "https://${GH_TOKEN}@github.com/immutable-js-oss/immutable-js.git" gh-pages 13 | 14 | # Remove existing files first 15 | rm -rf gh-pages/**/* 16 | rm -rf gh-pages/* 17 | 18 | # Copy over necessary files 19 | cp -r pages/out/* gh-pages/ 20 | 21 | HEADREV=`git rev-parse HEAD` 22 | echo $HEADREV 23 | 24 | cd gh-pages 25 | git config user.name "Travis CI" 26 | git config user.email "travis@travis-ci.com" 27 | git add -A . 28 | if git diff --staged --quiet; then 29 | echo "Nothing to publish" 30 | else 31 | git commit -a -m "Deploy $HEADREV to GitHub Pages" 32 | git push > /dev/null 2>&1 33 | echo "Pushed" 34 | fi 35 | -------------------------------------------------------------------------------- /resources/dist-stats.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const { exec } = require('child_process'); 9 | const { deflate } = require('zlib'); 10 | const fs = require('fs'); 11 | 12 | require('colors'); 13 | 14 | const fileContent = (filePath) => 15 | new Promise((resolve, reject) => 16 | fs.readFile(filePath, (error, out) => 17 | error ? reject(error) : resolve(out) 18 | ) 19 | ); 20 | 21 | const gitContent = (gitPath) => 22 | new Promise((resolve) => 23 | exec(`git show ${gitPath}`, (error, out) => { 24 | if (error) { 25 | console.log( 26 | `"git show ${gitPath}" failed, resulting in an empty diff.`.yellow 27 | ); 28 | resolve(''); 29 | return; 30 | } 31 | resolve(out); 32 | }) 33 | ); 34 | 35 | const deflateContent = (content) => 36 | new Promise((resolve, reject) => 37 | deflate(content, (error, out) => (error ? reject(error) : resolve(out))) 38 | ); 39 | 40 | const space = (n, s) => 41 | new Array(Math.max(0, 10 + n - (s || '').length)).join(' ') + (s || ''); 42 | 43 | const bytes = (b) => 44 | `${b.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')} bytes`; 45 | 46 | const diff = (n, o) => { 47 | const d = n - o; 48 | return d === 0 ? '' : d < 0 ? ` ${bytes(d)}`.green : ` +${bytes(d)}`.red; 49 | }; 50 | 51 | const pct = (s, b) => ` ${Math.floor(10000 * (1 - s / b)) / 100}%`.grey; 52 | 53 | Promise.all([ 54 | fileContent('dist/immutable.js'), 55 | gitContent('origin/npm:dist/immutable.js'), 56 | fileContent('dist/immutable.min.js'), 57 | gitContent('origin/npm:dist/immutable.min.js'), 58 | fileContent('dist/immutable.min.js').then(deflateContent), 59 | gitContent('origin/npm:dist/immutable.min.js').then(deflateContent), 60 | ]) 61 | .then((results) => results.map((result) => Buffer.byteLength(result, 'utf8'))) 62 | .then((results) => results.map((result) => parseInt(result, 10))) 63 | .then(([rawNew, rawOld, minNew, minOld, zipNew, zipOld]) => { 64 | console.log( 65 | ` Raw: ${space(14, bytes(rawNew).cyan)} ${space( 66 | 15, 67 | diff(rawNew, rawOld) 68 | )}` 69 | ); 70 | console.log( 71 | ` Min: ${space(14, bytes(minNew).cyan)}${pct(minNew, rawNew)}${space( 72 | 15, 73 | diff(minNew, minOld) 74 | )}` 75 | ); 76 | console.log( 77 | ` Zip: ${space(14, bytes(zipNew).cyan)}${pct(zipNew, rawNew)}${space( 78 | 15, 79 | diff(zipNew, zipOld) 80 | )}` 81 | ); 82 | }); 83 | -------------------------------------------------------------------------------- /resources/gitpublish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | # Copyright (c) 2014-present, Facebook, Inc. 4 | # 5 | # This source code is licensed under the MIT license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | # This script maintains a git branch which mirrors master but in a form that 9 | # what will eventually be deployed to npm, allowing npm dependencies to use: 10 | # 11 | # "immutable": "git://github.com/facebook/immutable-js.git#npm" 12 | # 13 | 14 | # Create empty npm directory 15 | rm -rf npm 16 | git clone -b npm "https://${GH_TOKEN}@github.com/immutable-js-oss/immutable-js.git" npm 17 | 18 | # Remove existing files first 19 | rm -rf npm/**/* 20 | rm -rf npm/* 21 | 22 | # Copy over necessary files 23 | cp -r dist npm/ 24 | cp README.md npm/ 25 | cp LICENSE npm/ 26 | 27 | # Ensure a vanilla package.json before deploying so other tools do not interpret 28 | # The built output as requiring any further transformation. 29 | node -e "var package = require('./package.json'); \ 30 | delete package.scripts; \ 31 | delete package.options; \ 32 | delete package.jest; \ 33 | delete package.devDependencies; \ 34 | require('fs').writeFileSync('./npm/package.json', JSON.stringify(package, null, 2));" 35 | 36 | # Retain marginal support for bower on this branch 37 | cp npm/package.json npm/bower.json 38 | 39 | HEADREV=`git rev-parse HEAD` 40 | echo $HEADREV 41 | 42 | cd npm 43 | git config user.name "Travis CI" 44 | git config user.email "travis@travis-ci.com" 45 | git add -A . 46 | if git diff --staged --quiet; then 47 | echo "Nothing to publish" 48 | else 49 | git commit -a -m "Deploy $HEADREV to NPM branch" 50 | git push > /dev/null 2>&1 51 | echo "Pushed" 52 | fi 53 | -------------------------------------------------------------------------------- /resources/identity.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/immutable-js-oss/immutable-js/43a7c4cd38b557e36a98ebc9f48e97470ef25d64/resources/identity.ai -------------------------------------------------------------------------------- /resources/immutable-global.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | module.exports = global.Immutable; 9 | -------------------------------------------------------------------------------- /resources/jest.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | declare var jasmine: any; 9 | 10 | declare function afterEach(fn: any): any; 11 | declare function beforeEach(fn: any): any; 12 | declare function describe(name: string, fn: any): void; 13 | declare var it: { 14 | (name: string, fn: any): void; 15 | only: (name: string, fn: any) => void; 16 | }; 17 | declare function expect(val: any): Expect; 18 | declare var jest: Jest; 19 | declare function pit(name: string, fn: any): void; 20 | declare function xdescribe(name: string, fn: any): void; 21 | declare function xit(name: string, fn: any): void; 22 | 23 | interface Expect { 24 | not: Expect; 25 | toThrow(message?: string): void; 26 | toBe(value: any): void; 27 | toEqual(value: any): void; 28 | toValueEqual(value: any): void; 29 | toBeFalsy(): void; 30 | toBeTruthy(): void; 31 | toBeNull(): void; 32 | toBeUndefined(): void; 33 | toBeDefined(): void; 34 | toMatch(regexp: RegExp): void; 35 | toContain(string: string): void; 36 | toBeCloseTo(number: number, delta: number): void; 37 | toBeGreaterThan(number: number): void; 38 | toBeLessThan(number: number): void; 39 | toBeCalled(): void; 40 | toBeCalledWith(...arguments): void; 41 | lastCalledWith(...arguments): void; 42 | } 43 | 44 | interface Jest { 45 | autoMockOff(): void; 46 | autoMockOn(): void; 47 | clearAllTimers(): void; 48 | dontMock(moduleName: string): void; 49 | genMockFromModule(moduleObj: Object): Object; 50 | genMockFunction(): MockFunction; 51 | genMockFn(): MockFunction; 52 | mock(moduleName: string): void; 53 | runAllTicks(): void; 54 | runAllTimers(): void; 55 | runOnlyPendingTimers(): void; 56 | setMock(moduleName: string, moduleExports: Object): void; 57 | } 58 | 59 | interface MockFunction { 60 | (...arguments): any; 61 | mock: { 62 | calls: Array>; 63 | instances: Array; 64 | }; 65 | mockClear(): void; 66 | mockImplementation(fn: Function): MockFunction; 67 | mockImpl(fn: Function): MockFunction; 68 | mockReturnThis(): MockFunction; 69 | mockReturnValue(value: any): MockFunction; 70 | mockReturnValueOnce(value: any): MockFunction; 71 | } 72 | 73 | // Allow importing jasmine-check 74 | declare module 'jasmine-check' { 75 | export function install(global?: any): void; 76 | } 77 | declare var check: any; 78 | declare var gen: any; 79 | -------------------------------------------------------------------------------- /resources/jestPreprocessor.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | var typescript = require('typescript'); 9 | const makeSynchronous = require('make-synchronous'); 10 | 11 | const TYPESCRIPT_OPTIONS = { 12 | noEmitOnError: true, 13 | target: typescript.ScriptTarget.ES2015, 14 | module: typescript.ModuleKind.CommonJS, 15 | strictNullChecks: true, 16 | sourceMap: true, 17 | inlineSourceMap: true, 18 | }; 19 | 20 | function transpileTypeScript(src, path) { 21 | return typescript.transpile(src, TYPESCRIPT_OPTIONS, path, []); 22 | } 23 | 24 | function transpileJavaScript(src, path) { 25 | // Need to make this sync by calling `makeSynchronous` 26 | // while https://github.com/facebook/jest/issues/9504 is not resolved 27 | const fn = makeSynchronous(async (path) => { 28 | const rollup = require('rollup'); 29 | const buble = require('rollup-plugin-buble'); 30 | const commonjs = require('rollup-plugin-commonjs'); 31 | const json = require('rollup-plugin-json'); 32 | const stripBanner = require('rollup-plugin-strip-banner'); 33 | 34 | // same input options as in rollup-config.js 35 | const inputOptions = { 36 | input: path, 37 | onwarn: () => {}, 38 | plugins: [commonjs(), json(), stripBanner(), buble()], 39 | }; 40 | 41 | const bundle = await rollup.rollup(inputOptions); 42 | 43 | const output = await bundle.generate({ 44 | file: path, 45 | format: 'cjs', 46 | sourcemap: true, 47 | }); 48 | 49 | return { code: output.code, map: output.map }; 50 | }); 51 | 52 | return fn(path); 53 | } 54 | 55 | module.exports = { 56 | process(src, path) { 57 | if (path.endsWith('__tests__/MultiRequire.js')) { 58 | // exit early for multi-require as we explicitly want to have several instances 59 | return src; 60 | } 61 | 62 | if (path.endsWith('.ts') || path.endsWith('.tsx')) { 63 | return transpileTypeScript(src, path); 64 | } 65 | 66 | return transpileJavaScript(src, path); 67 | }, 68 | }; 69 | -------------------------------------------------------------------------------- /resources/jestResolver.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const pkg = require('../package.json'); 3 | 4 | module.exports = (request, options) => { 5 | if (request === 'immutable') { 6 | if (process.env.CI) { 7 | // In CI environment, let's test the real builded file to be sure that the build does is not broken 8 | return path.resolve(options.rootDir, pkg.main); 9 | } 10 | 11 | // in development mode, we want sourcemaps and live reload, etc, so let's point to the src/ directory 12 | return path.resolve('src', 'Immutable.js'); 13 | } 14 | 15 | // Call the defaultResolver, if we want to load non-immutable 16 | return options.defaultResolver(request, options); 17 | }; 18 | -------------------------------------------------------------------------------- /resources/react-global.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | module.exports = global.React; 9 | -------------------------------------------------------------------------------- /resources/rollup-config-es.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import fs from 'fs'; 9 | import path from 'path'; 10 | import buble from 'rollup-plugin-buble'; 11 | import commonjs from 'rollup-plugin-commonjs'; 12 | import json from 'rollup-plugin-json'; 13 | import stripBanner from 'rollup-plugin-strip-banner'; 14 | 15 | const copyright = fs.readFileSync(path.join('resources', 'COPYRIGHT'), 'utf-8'); 16 | 17 | const SRC_DIR = path.resolve('src'); 18 | const DIST_DIR = path.resolve('dist'); 19 | 20 | export default { 21 | input: path.join(SRC_DIR, 'Immutable.js'), 22 | output: { 23 | banner: copyright, 24 | name: 'Immutable', 25 | file: path.join(DIST_DIR, 'immutable.es.js'), 26 | format: 'es', 27 | sourcemap: false, 28 | }, 29 | plugins: [commonjs(), json(), stripBanner(), buble()], 30 | }; 31 | -------------------------------------------------------------------------------- /resources/rollup-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import fs from 'fs'; 9 | import path from 'path'; 10 | import { minify } from 'uglify-js'; 11 | import buble from 'rollup-plugin-buble'; 12 | import commonjs from 'rollup-plugin-commonjs'; 13 | import json from 'rollup-plugin-json'; 14 | import saveLicense from 'uglify-save-license'; 15 | import stripBanner from 'rollup-plugin-strip-banner'; 16 | 17 | const copyright = fs.readFileSync(path.join('resources', 'COPYRIGHT'), 'utf-8'); 18 | 19 | const SRC_DIR = path.resolve('src'); 20 | const DIST_DIR = path.resolve('dist'); 21 | 22 | export default { 23 | input: path.join(SRC_DIR, 'Immutable.js'), 24 | output: { 25 | banner: copyright, 26 | name: 'Immutable', 27 | exports: 'named', 28 | file: path.join(DIST_DIR, 'immutable.js'), 29 | format: 'umd', 30 | sourcemap: false, 31 | }, 32 | plugins: [ 33 | commonjs(), 34 | json(), 35 | stripBanner(), 36 | buble(), 37 | { 38 | name: 'uglify', 39 | transformBundle(code) { 40 | const result = minify(code, { 41 | fromString: true, 42 | mangle: { toplevel: true }, 43 | output: { max_line_len: 2048, comments: saveLicense }, 44 | compress: { comparisons: true, pure_getters: true, unsafe: true }, 45 | }); 46 | 47 | if (!fs.existsSync(DIST_DIR)) { 48 | fs.mkdirSync(DIST_DIR); 49 | } 50 | 51 | fs.writeFileSync( 52 | path.join(DIST_DIR, 'immutable.min.js'), 53 | result.code, 54 | 'utf8' 55 | ); 56 | }, 57 | }, 58 | ], 59 | }; 60 | -------------------------------------------------------------------------------- /src/Collection.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { Seq, KeyedSeq, IndexedSeq, SetSeq } from './Seq'; 9 | import { isCollection } from './predicates/isCollection'; 10 | import { isKeyed } from './predicates/isKeyed'; 11 | import { isIndexed } from './predicates/isIndexed'; 12 | import { isAssociative } from './predicates/isAssociative'; 13 | 14 | export class Collection { 15 | constructor(value) { 16 | return isCollection(value) ? value : Seq(value); 17 | } 18 | } 19 | 20 | export class KeyedCollection extends Collection { 21 | constructor(value) { 22 | return isKeyed(value) ? value : KeyedSeq(value); 23 | } 24 | } 25 | 26 | export class IndexedCollection extends Collection { 27 | constructor(value) { 28 | return isIndexed(value) ? value : IndexedSeq(value); 29 | } 30 | } 31 | 32 | export class SetCollection extends Collection { 33 | constructor(value) { 34 | return isCollection(value) && !isAssociative(value) ? value : SetSeq(value); 35 | } 36 | } 37 | 38 | Collection.Keyed = KeyedCollection; 39 | Collection.Indexed = IndexedCollection; 40 | Collection.Set = SetCollection; 41 | -------------------------------------------------------------------------------- /src/Iterator.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export const ITERATE_KEYS = 0; 9 | export const ITERATE_VALUES = 1; 10 | export const ITERATE_ENTRIES = 2; 11 | 12 | const REAL_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; 13 | const FAUX_ITERATOR_SYMBOL = '@@iterator'; 14 | 15 | export const ITERATOR_SYMBOL = REAL_ITERATOR_SYMBOL || FAUX_ITERATOR_SYMBOL; 16 | 17 | export class Iterator { 18 | constructor(next) { 19 | this.next = next; 20 | } 21 | 22 | toString() { 23 | return '[Iterator]'; 24 | } 25 | } 26 | 27 | Iterator.KEYS = ITERATE_KEYS; 28 | Iterator.VALUES = ITERATE_VALUES; 29 | Iterator.ENTRIES = ITERATE_ENTRIES; 30 | 31 | Iterator.prototype.inspect = Iterator.prototype.toSource = function () { 32 | return this.toString(); 33 | }; 34 | Iterator.prototype[ITERATOR_SYMBOL] = function () { 35 | return this; 36 | }; 37 | 38 | export function iteratorValue(type, k, v, iteratorResult) { 39 | const value = type === 0 ? k : type === 1 ? v : [k, v]; 40 | iteratorResult 41 | ? (iteratorResult.value = value) 42 | : (iteratorResult = { 43 | value: value, 44 | done: false, 45 | }); 46 | return iteratorResult; 47 | } 48 | 49 | export function iteratorDone() { 50 | return { value: undefined, done: true }; 51 | } 52 | 53 | export function hasIterator(maybeIterable) { 54 | return !!getIteratorFn(maybeIterable); 55 | } 56 | 57 | export function isIterator(maybeIterator) { 58 | return maybeIterator && typeof maybeIterator.next === 'function'; 59 | } 60 | 61 | export function getIterator(iterable) { 62 | const iteratorFn = getIteratorFn(iterable); 63 | return iteratorFn && iteratorFn.call(iterable); 64 | } 65 | 66 | function getIteratorFn(iterable) { 67 | const iteratorFn = 68 | iterable && 69 | ((REAL_ITERATOR_SYMBOL && iterable[REAL_ITERATOR_SYMBOL]) || 70 | iterable[FAUX_ITERATOR_SYMBOL]); 71 | if (typeof iteratorFn === 'function') { 72 | return iteratorFn; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Math.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export const imul = 9 | typeof Math.imul === 'function' && Math.imul(0xffffffff, 2) === -2 10 | ? Math.imul 11 | : function imul(a, b) { 12 | a |= 0; // int 13 | b |= 0; // int 14 | const c = a & 0xffff; 15 | const d = b & 0xffff; 16 | // Shift by 0 fixes the sign on the high part. 17 | return (c * d + ((((a >>> 16) * d + c * (b >>> 16)) << 16) >>> 0)) | 0; // int 18 | }; 19 | 20 | // v8 has an optimization for storing 31-bit signed numbers. 21 | // Values which have either 00 or 11 as the high order bits qualify. 22 | // This function drops the highest order bit in a signed number, maintaining 23 | // the sign bit. 24 | export function smi(i32) { 25 | return ((i32 >>> 1) & 0x40000000) | (i32 & 0xbfffffff); 26 | } 27 | -------------------------------------------------------------------------------- /src/OrderedSet.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { SetCollection, KeyedCollection } from './Collection'; 9 | import { IS_ORDERED_SYMBOL } from './predicates/isOrdered'; 10 | import { isOrderedSet } from './predicates/isOrderedSet'; 11 | import { IndexedCollectionPrototype } from './CollectionImpl'; 12 | import { Set } from './Set'; 13 | import { emptyOrderedMap } from './OrderedMap'; 14 | import assertNotInfinite from './utils/assertNotInfinite'; 15 | 16 | export class OrderedSet extends Set { 17 | // @pragma Construction 18 | 19 | constructor(value) { 20 | return value === null || value === undefined 21 | ? emptyOrderedSet() 22 | : isOrderedSet(value) 23 | ? value 24 | : emptyOrderedSet().withMutations((set) => { 25 | const iter = SetCollection(value); 26 | assertNotInfinite(iter.size); 27 | iter.forEach((v) => set.add(v)); 28 | }); 29 | } 30 | 31 | static of(/*...values*/) { 32 | return this(arguments); 33 | } 34 | 35 | static fromKeys(value) { 36 | return this(KeyedCollection(value).keySeq()); 37 | } 38 | 39 | toString() { 40 | return this.__toString('OrderedSet {', '}'); 41 | } 42 | } 43 | 44 | OrderedSet.isOrderedSet = isOrderedSet; 45 | 46 | const OrderedSetPrototype = OrderedSet.prototype; 47 | OrderedSetPrototype[IS_ORDERED_SYMBOL] = true; 48 | OrderedSetPrototype.zip = IndexedCollectionPrototype.zip; 49 | OrderedSetPrototype.zipWith = IndexedCollectionPrototype.zipWith; 50 | 51 | OrderedSetPrototype.__empty = emptyOrderedSet; 52 | OrderedSetPrototype.__make = makeOrderedSet; 53 | 54 | function makeOrderedSet(map, ownerID) { 55 | const set = Object.create(OrderedSetPrototype); 56 | set.size = map ? map.size : 0; 57 | set._map = map; 58 | set.__ownerID = ownerID; 59 | return set; 60 | } 61 | 62 | let EMPTY_ORDERED_SET; 63 | function emptyOrderedSet() { 64 | return ( 65 | EMPTY_ORDERED_SET || (EMPTY_ORDERED_SET = makeOrderedSet(emptyOrderedMap())) 66 | ); 67 | } 68 | -------------------------------------------------------------------------------- /src/Repeat.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { wholeSlice, resolveBegin, resolveEnd } from './TrieUtils'; 9 | import { IndexedSeq } from './Seq'; 10 | import { is } from './is'; 11 | import { Iterator, iteratorValue, iteratorDone } from './Iterator'; 12 | 13 | import deepEqual from './utils/deepEqual'; 14 | 15 | /** 16 | * Returns a lazy Seq of `value` repeated `times` times. When `times` is 17 | * undefined, returns an infinite sequence of `value`. 18 | */ 19 | export class Repeat extends IndexedSeq { 20 | constructor(value, times) { 21 | if (!(this instanceof Repeat)) { 22 | return new Repeat(value, times); 23 | } 24 | this._value = value; 25 | this.size = times === undefined ? Infinity : Math.max(0, times); 26 | if (this.size === 0) { 27 | if (EMPTY_REPEAT) { 28 | return EMPTY_REPEAT; 29 | } 30 | EMPTY_REPEAT = this; 31 | } 32 | } 33 | 34 | toString() { 35 | if (this.size === 0) { 36 | return 'Repeat []'; 37 | } 38 | return 'Repeat [ ' + this._value + ' ' + this.size + ' times ]'; 39 | } 40 | 41 | get(index, notSetValue) { 42 | return this.has(index) ? this._value : notSetValue; 43 | } 44 | 45 | includes(searchValue) { 46 | return is(this._value, searchValue); 47 | } 48 | 49 | slice(begin, end) { 50 | const size = this.size; 51 | return wholeSlice(begin, end, size) 52 | ? this 53 | : new Repeat( 54 | this._value, 55 | resolveEnd(end, size) - resolveBegin(begin, size) 56 | ); 57 | } 58 | 59 | reverse() { 60 | return this; 61 | } 62 | 63 | indexOf(searchValue) { 64 | if (is(this._value, searchValue)) { 65 | return 0; 66 | } 67 | return -1; 68 | } 69 | 70 | lastIndexOf(searchValue) { 71 | if (is(this._value, searchValue)) { 72 | return this.size; 73 | } 74 | return -1; 75 | } 76 | 77 | __iterate(fn, reverse) { 78 | const size = this.size; 79 | let i = 0; 80 | while (i !== size) { 81 | if (fn(this._value, reverse ? size - ++i : i++, this) === false) { 82 | break; 83 | } 84 | } 85 | return i; 86 | } 87 | 88 | __iterator(type, reverse) { 89 | const size = this.size; 90 | let i = 0; 91 | return new Iterator(() => 92 | i === size 93 | ? iteratorDone() 94 | : iteratorValue(type, reverse ? size - ++i : i++, this._value) 95 | ); 96 | } 97 | 98 | equals(other) { 99 | return other instanceof Repeat 100 | ? is(this._value, other._value) 101 | : deepEqual(other); 102 | } 103 | } 104 | 105 | let EMPTY_REPEAT; 106 | -------------------------------------------------------------------------------- /src/TrieUtils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Used for setting prototype methods that IE8 chokes on. 9 | export const DELETE = 'delete'; 10 | 11 | // Constants describing the size of trie nodes. 12 | export const SHIFT = 5; // Resulted in best performance after ______? 13 | export const SIZE = 1 << SHIFT; 14 | export const MASK = SIZE - 1; 15 | 16 | // A consistent shared value representing "not set" which equals nothing other 17 | // than itself, and nothing that could be provided externally. 18 | export const NOT_SET = {}; 19 | 20 | // Boolean references, Rough equivalent of `bool &`. 21 | export function MakeRef() { 22 | return { value: false }; 23 | } 24 | 25 | export function SetRef(ref) { 26 | if (ref) { 27 | ref.value = true; 28 | } 29 | } 30 | 31 | // A function which returns a value representing an "owner" for transient writes 32 | // to tries. The return value will only ever equal itself, and will not equal 33 | // the return of any subsequent call of this function. 34 | export function OwnerID() {} 35 | 36 | export function ensureSize(iter) { 37 | if (iter.size === undefined) { 38 | iter.size = iter.__iterate(returnTrue); 39 | } 40 | return iter.size; 41 | } 42 | 43 | export function wrapIndex(iter, index) { 44 | // This implements "is array index" which the ECMAString spec defines as: 45 | // 46 | // A String property name P is an array index if and only if 47 | // ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal 48 | // to 2^32−1. 49 | // 50 | // http://www.ecma-international.org/ecma-262/6.0/#sec-array-exotic-objects 51 | if (typeof index !== 'number') { 52 | const uint32Index = index >>> 0; // N >>> 0 is shorthand for ToUint32 53 | if ('' + uint32Index !== index || uint32Index === 4294967295) { 54 | return NaN; 55 | } 56 | index = uint32Index; 57 | } 58 | return index < 0 ? ensureSize(iter) + index : index; 59 | } 60 | 61 | export function returnTrue() { 62 | return true; 63 | } 64 | 65 | export function wholeSlice(begin, end, size) { 66 | return ( 67 | ((begin === 0 && !isNeg(begin)) || 68 | (size !== undefined && begin <= -size)) && 69 | (end === undefined || (size !== undefined && end >= size)) 70 | ); 71 | } 72 | 73 | export function resolveBegin(begin, size) { 74 | return resolveIndex(begin, size, 0); 75 | } 76 | 77 | export function resolveEnd(end, size) { 78 | return resolveIndex(end, size, size); 79 | } 80 | 81 | function resolveIndex(index, size, defaultIndex) { 82 | // Sanitize indices using this shorthand for ToInt32(argument) 83 | // http://www.ecma-international.org/ecma-262/6.0/#sec-toint32 84 | return index === undefined 85 | ? defaultIndex 86 | : isNeg(index) 87 | ? size === Infinity 88 | ? size 89 | : Math.max(0, size + index) | 0 90 | : size === undefined || size === index 91 | ? index 92 | : Math.min(size, index) | 0; 93 | } 94 | 95 | function isNeg(value) { 96 | // Account for -0 which is negative, but not less than 0. 97 | return value < 0 || (value === 0 && 1 / value === -Infinity); 98 | } 99 | -------------------------------------------------------------------------------- /src/fromJS.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { KeyedSeq, IndexedSeq } from './Seq'; 9 | import { isKeyed } from './predicates/isKeyed'; 10 | import isPlainObj from './utils/isPlainObj'; 11 | 12 | export function fromJS(value, converter) { 13 | return fromJSWith( 14 | [], 15 | converter || defaultConverter, 16 | value, 17 | '', 18 | converter && converter.length > 2 ? [] : undefined, 19 | { '': value } 20 | ); 21 | } 22 | 23 | function fromJSWith(stack, converter, value, key, keyPath, parentValue) { 24 | const toSeq = Array.isArray(value) 25 | ? IndexedSeq 26 | : isPlainObj(value) 27 | ? KeyedSeq 28 | : null; 29 | if (toSeq) { 30 | if (~stack.indexOf(value)) { 31 | throw new TypeError('Cannot convert circular structure to Immutable'); 32 | } 33 | stack.push(value); 34 | keyPath && key !== '' && keyPath.push(key); 35 | const converted = converter.call( 36 | parentValue, 37 | key, 38 | toSeq(value).map((v, k) => 39 | fromJSWith(stack, converter, v, k, keyPath, value) 40 | ), 41 | keyPath && keyPath.slice() 42 | ); 43 | stack.pop(); 44 | keyPath && keyPath.pop(); 45 | return converted; 46 | } 47 | return value; 48 | } 49 | 50 | function defaultConverter(k, v) { 51 | return isKeyed(v) ? v.toMap() : v.toList(); 52 | } 53 | -------------------------------------------------------------------------------- /src/functional/get.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { isImmutable } from '../predicates/isImmutable'; 9 | import { has } from './has'; 10 | 11 | export function get(collection, key, notSetValue) { 12 | return isImmutable(collection) 13 | ? collection.get(key, notSetValue) 14 | : !has(collection, key) 15 | ? notSetValue 16 | : typeof collection.get === 'function' 17 | ? collection.get(key) 18 | : collection[key]; 19 | } 20 | -------------------------------------------------------------------------------- /src/functional/getIn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import coerceKeyPath from '../utils/coerceKeyPath'; 9 | import { NOT_SET } from '../TrieUtils'; 10 | import { get } from './get'; 11 | 12 | export function getIn(collection, searchKeyPath, notSetValue) { 13 | const keyPath = coerceKeyPath(searchKeyPath); 14 | let i = 0; 15 | while (i !== keyPath.length) { 16 | collection = get(collection, keyPath[i++], NOT_SET); 17 | if (collection === NOT_SET) { 18 | return notSetValue; 19 | } 20 | } 21 | return collection; 22 | } 23 | -------------------------------------------------------------------------------- /src/functional/has.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { isImmutable } from '../predicates/isImmutable'; 9 | import hasOwnProperty from '../utils/hasOwnProperty'; 10 | import isDataStructure from '../utils/isDataStructure'; 11 | 12 | export function has(collection, key) { 13 | return isImmutable(collection) 14 | ? collection.has(key) 15 | : isDataStructure(collection) && hasOwnProperty.call(collection, key); 16 | } 17 | -------------------------------------------------------------------------------- /src/functional/hasIn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { getIn } from './getIn'; 9 | import { NOT_SET } from '../TrieUtils'; 10 | 11 | export function hasIn(collection, keyPath) { 12 | return getIn(collection, keyPath, NOT_SET) !== NOT_SET; 13 | } 14 | -------------------------------------------------------------------------------- /src/functional/merge.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { isImmutable } from '../predicates/isImmutable'; 9 | import { IndexedCollection, KeyedCollection } from '../Collection'; 10 | import hasOwnProperty from '../utils/hasOwnProperty'; 11 | import isDataStructure from '../utils/isDataStructure'; 12 | import shallowCopy from '../utils/shallowCopy'; 13 | 14 | export function merge(collection, ...sources) { 15 | return mergeWithSources(collection, sources); 16 | } 17 | 18 | export function mergeWith(merger, collection, ...sources) { 19 | return mergeWithSources(collection, sources, merger); 20 | } 21 | 22 | export function mergeDeep(collection, ...sources) { 23 | return mergeDeepWithSources(collection, sources); 24 | } 25 | 26 | export function mergeDeepWith(merger, collection, ...sources) { 27 | return mergeDeepWithSources(collection, sources, merger); 28 | } 29 | 30 | export function mergeDeepWithSources(collection, sources, merger) { 31 | return mergeWithSources(collection, sources, deepMergerWith(merger)); 32 | } 33 | 34 | export function mergeWithSources(collection, sources, merger) { 35 | if (!isDataStructure(collection)) { 36 | throw new TypeError( 37 | 'Cannot merge into non-data-structure value: ' + collection 38 | ); 39 | } 40 | if (isImmutable(collection)) { 41 | return typeof merger === 'function' && collection.mergeWith 42 | ? collection.mergeWith(merger, ...sources) 43 | : collection.merge 44 | ? collection.merge(...sources) 45 | : collection.concat(...sources); 46 | } 47 | const isArray = Array.isArray(collection); 48 | let merged = collection; 49 | const Collection = isArray ? IndexedCollection : KeyedCollection; 50 | const mergeItem = isArray 51 | ? (value) => { 52 | // Copy on write 53 | if (merged === collection) { 54 | merged = shallowCopy(merged); 55 | } 56 | merged.push(value); 57 | } 58 | : (value, key) => { 59 | const hasVal = hasOwnProperty.call(merged, key); 60 | const nextVal = 61 | hasVal && merger ? merger(merged[key], value, key) : value; 62 | if (!hasVal || nextVal !== merged[key]) { 63 | // Copy on write 64 | if (merged === collection) { 65 | merged = shallowCopy(merged); 66 | } 67 | merged[key] = nextVal; 68 | } 69 | }; 70 | for (let i = 0; i < sources.length; i++) { 71 | Collection(sources[i]).forEach(mergeItem); 72 | } 73 | return merged; 74 | } 75 | 76 | function deepMergerWith(merger) { 77 | function deepMerger(oldValue, newValue, key) { 78 | return isDataStructure(oldValue) && isDataStructure(newValue) 79 | ? mergeWithSources(oldValue, [newValue], deepMerger) 80 | : merger 81 | ? merger(oldValue, newValue, key) 82 | : newValue; 83 | } 84 | return deepMerger; 85 | } 86 | -------------------------------------------------------------------------------- /src/functional/remove.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { isImmutable } from '../predicates/isImmutable'; 9 | import hasOwnProperty from '../utils/hasOwnProperty'; 10 | import isDataStructure from '../utils/isDataStructure'; 11 | import shallowCopy from '../utils/shallowCopy'; 12 | 13 | export function remove(collection, key) { 14 | if (!isDataStructure(collection)) { 15 | throw new TypeError( 16 | 'Cannot update non-data-structure value: ' + collection 17 | ); 18 | } 19 | if (isImmutable(collection)) { 20 | if (!collection.remove) { 21 | throw new TypeError( 22 | 'Cannot update immutable value without .remove() method: ' + collection 23 | ); 24 | } 25 | return collection.remove(key); 26 | } 27 | if (!hasOwnProperty.call(collection, key)) { 28 | return collection; 29 | } 30 | const collectionCopy = shallowCopy(collection); 31 | if (Array.isArray(collectionCopy)) { 32 | collectionCopy.splice(key, 1); 33 | } else { 34 | delete collectionCopy[key]; 35 | } 36 | return collectionCopy; 37 | } 38 | -------------------------------------------------------------------------------- /src/functional/removeIn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { updateIn } from './updateIn'; 9 | import { NOT_SET } from '../TrieUtils'; 10 | 11 | export function removeIn(collection, keyPath) { 12 | return updateIn(collection, keyPath, () => NOT_SET); 13 | } 14 | -------------------------------------------------------------------------------- /src/functional/set.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { isImmutable } from '../predicates/isImmutable'; 9 | import hasOwnProperty from '../utils/hasOwnProperty'; 10 | import isDataStructure from '../utils/isDataStructure'; 11 | import shallowCopy from '../utils/shallowCopy'; 12 | 13 | export function set(collection, key, value) { 14 | if (!isDataStructure(collection)) { 15 | throw new TypeError( 16 | 'Cannot update non-data-structure value: ' + collection 17 | ); 18 | } 19 | if (isImmutable(collection)) { 20 | if (!collection.set) { 21 | throw new TypeError( 22 | 'Cannot update immutable value without .set() method: ' + collection 23 | ); 24 | } 25 | return collection.set(key, value); 26 | } 27 | if (hasOwnProperty.call(collection, key) && value === collection[key]) { 28 | return collection; 29 | } 30 | const collectionCopy = shallowCopy(collection); 31 | collectionCopy[key] = value; 32 | return collectionCopy; 33 | } 34 | -------------------------------------------------------------------------------- /src/functional/setIn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { updateIn } from './updateIn'; 9 | import { NOT_SET } from '../TrieUtils'; 10 | 11 | export function setIn(collection, keyPath, value) { 12 | return updateIn(collection, keyPath, NOT_SET, () => value); 13 | } 14 | -------------------------------------------------------------------------------- /src/functional/update.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { updateIn } from './updateIn'; 9 | 10 | export function update(collection, key, notSetValue, updater) { 11 | return updateIn(collection, [key], notSetValue, updater); 12 | } 13 | -------------------------------------------------------------------------------- /src/functional/updateIn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { isImmutable } from '../predicates/isImmutable'; 9 | import coerceKeyPath from '../utils/coerceKeyPath'; 10 | import isDataStructure from '../utils/isDataStructure'; 11 | import quoteString from '../utils/quoteString'; 12 | import { NOT_SET } from '../TrieUtils'; 13 | import { emptyMap } from '../Map'; 14 | import { get } from './get'; 15 | import { remove } from './remove'; 16 | import { set } from './set'; 17 | 18 | export function updateIn(collection, keyPath, notSetValue, updater) { 19 | if (!updater) { 20 | updater = notSetValue; 21 | notSetValue = undefined; 22 | } 23 | const updatedValue = updateInDeeply( 24 | isImmutable(collection), 25 | collection, 26 | coerceKeyPath(keyPath), 27 | 0, 28 | notSetValue, 29 | updater 30 | ); 31 | return updatedValue === NOT_SET ? notSetValue : updatedValue; 32 | } 33 | 34 | function updateInDeeply( 35 | inImmutable, 36 | existing, 37 | keyPath, 38 | i, 39 | notSetValue, 40 | updater 41 | ) { 42 | const wasNotSet = existing === NOT_SET; 43 | if (i === keyPath.length) { 44 | const existingValue = wasNotSet ? notSetValue : existing; 45 | const newValue = updater(existingValue); 46 | return newValue === existingValue ? existing : newValue; 47 | } 48 | if (!wasNotSet && !isDataStructure(existing)) { 49 | throw new TypeError( 50 | 'Cannot update within non-data-structure value in path [' + 51 | keyPath.slice(0, i).map(quoteString) + 52 | ']: ' + 53 | existing 54 | ); 55 | } 56 | const key = keyPath[i]; 57 | const nextExisting = wasNotSet ? NOT_SET : get(existing, key, NOT_SET); 58 | const nextUpdated = updateInDeeply( 59 | nextExisting === NOT_SET ? inImmutable : isImmutable(nextExisting), 60 | nextExisting, 61 | keyPath, 62 | i + 1, 63 | notSetValue, 64 | updater 65 | ); 66 | return nextUpdated === nextExisting 67 | ? existing 68 | : nextUpdated === NOT_SET 69 | ? remove(existing, key) 70 | : set( 71 | wasNotSet ? (inImmutable ? emptyMap() : {}) : existing, 72 | key, 73 | nextUpdated 74 | ); 75 | } 76 | -------------------------------------------------------------------------------- /src/is.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { isValueObject } from './predicates/isValueObject'; 9 | 10 | /** 11 | * An extension of the "same-value" algorithm as [described for use by ES6 Map 12 | * and Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality) 13 | * 14 | * NaN is considered the same as NaN, however -0 and 0 are considered the same 15 | * value, which is different from the algorithm described by 16 | * [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). 17 | * 18 | * This is extended further to allow Objects to describe the values they 19 | * represent, by way of `valueOf` or `equals` (and `hashCode`). 20 | * 21 | * Note: because of this extension, the key equality of Immutable.Map and the 22 | * value equality of Immutable.Set will differ from ES6 Map and Set. 23 | * 24 | * ### Defining custom values 25 | * 26 | * The easiest way to describe the value an object represents is by implementing 27 | * `valueOf`. For example, `Date` represents a value by returning a unix 28 | * timestamp for `valueOf`: 29 | * 30 | * var date1 = new Date(1234567890000); // Fri Feb 13 2009 ... 31 | * var date2 = new Date(1234567890000); 32 | * date1.valueOf(); // 1234567890000 33 | * assert( date1 !== date2 ); 34 | * assert( Immutable.is( date1, date2 ) ); 35 | * 36 | * Note: overriding `valueOf` may have other implications if you use this object 37 | * where JavaScript expects a primitive, such as implicit string coercion. 38 | * 39 | * For more complex types, especially collections, implementing `valueOf` may 40 | * not be performant. An alternative is to implement `equals` and `hashCode`. 41 | * 42 | * `equals` takes another object, presumably of similar type, and returns true 43 | * if it is equal. Equality is symmetrical, so the same result should be 44 | * returned if this and the argument are flipped. 45 | * 46 | * assert( a.equals(b) === b.equals(a) ); 47 | * 48 | * `hashCode` returns a 32bit integer number representing the object which will 49 | * be used to determine how to store the value object in a Map or Set. You must 50 | * provide both or neither methods, one must not exist without the other. 51 | * 52 | * Also, an important relationship between these methods must be upheld: if two 53 | * values are equal, they *must* return the same hashCode. If the values are not 54 | * equal, they might have the same hashCode; this is called a hash collision, 55 | * and while undesirable for performance reasons, it is acceptable. 56 | * 57 | * if (a.equals(b)) { 58 | * assert( a.hashCode() === b.hashCode() ); 59 | * } 60 | * 61 | * All Immutable collections are Value Objects: they implement `equals()` 62 | * and `hashCode()`. 63 | */ 64 | export function is(valueA, valueB) { 65 | if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) { 66 | return true; 67 | } 68 | if (!valueA || !valueB) { 69 | return false; 70 | } 71 | if ( 72 | typeof valueA.valueOf === 'function' && 73 | typeof valueB.valueOf === 'function' 74 | ) { 75 | valueA = valueA.valueOf(); 76 | valueB = valueB.valueOf(); 77 | if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) { 78 | return true; 79 | } 80 | if (!valueA || !valueB) { 81 | return false; 82 | } 83 | } 84 | return !!( 85 | isValueObject(valueA) && 86 | isValueObject(valueB) && 87 | valueA.equals(valueB) 88 | ); 89 | } 90 | -------------------------------------------------------------------------------- /src/methods/README.md: -------------------------------------------------------------------------------- 1 | These files represent common methods on Collection types, each will contain 2 | references to "this" - expecting to be called as a prototypal method. 3 | 4 | They are separated into individual files to avoid circular dependencies when 5 | possible, and to allow their use in multiple different Collections. 6 | -------------------------------------------------------------------------------- /src/methods/asImmutable.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export function asImmutable() { 9 | return this.__ensureOwner(); 10 | } 11 | -------------------------------------------------------------------------------- /src/methods/asMutable.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { OwnerID } from '../TrieUtils'; 9 | 10 | export function asMutable() { 11 | return this.__ownerID ? this : this.__ensureOwner(new OwnerID()); 12 | } 13 | -------------------------------------------------------------------------------- /src/methods/deleteIn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { removeIn } from '../functional/removeIn'; 9 | 10 | export function deleteIn(keyPath) { 11 | return removeIn(this, keyPath); 12 | } 13 | -------------------------------------------------------------------------------- /src/methods/getIn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { getIn as _getIn } from '../functional/getIn'; 9 | 10 | export function getIn(searchKeyPath, notSetValue) { 11 | return _getIn(this, searchKeyPath, notSetValue); 12 | } 13 | -------------------------------------------------------------------------------- /src/methods/hasIn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { hasIn as _hasIn } from '../functional/hasIn'; 9 | 10 | export function hasIn(searchKeyPath) { 11 | return _hasIn(this, searchKeyPath); 12 | } 13 | -------------------------------------------------------------------------------- /src/methods/merge.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { KeyedCollection } from '../Collection'; 9 | import { NOT_SET } from '../TrieUtils'; 10 | import { update } from '../functional/update'; 11 | 12 | export function merge(...iters) { 13 | return mergeIntoKeyedWith(this, iters); 14 | } 15 | 16 | export function mergeWith(merger, ...iters) { 17 | if (typeof merger !== 'function') { 18 | throw new TypeError('Invalid merger function: ' + merger); 19 | } 20 | return mergeIntoKeyedWith(this, iters, merger); 21 | } 22 | 23 | function mergeIntoKeyedWith(collection, collections, merger) { 24 | const iters = []; 25 | for (let ii = 0; ii < collections.length; ii++) { 26 | const collection = KeyedCollection(collections[ii]); 27 | if (collection.size !== 0) { 28 | iters.push(collection); 29 | } 30 | } 31 | if (iters.length === 0) { 32 | return collection; 33 | } 34 | if ( 35 | collection.toSeq().size === 0 && 36 | !collection.__ownerID && 37 | iters.length === 1 38 | ) { 39 | return collection.constructor(iters[0]); 40 | } 41 | return collection.withMutations((collection) => { 42 | const mergeIntoCollection = merger 43 | ? (value, key) => { 44 | update(collection, key, NOT_SET, (oldVal) => 45 | oldVal === NOT_SET ? value : merger(oldVal, value, key) 46 | ); 47 | } 48 | : (value, key) => { 49 | collection.set(key, value); 50 | }; 51 | for (let ii = 0; ii < iters.length; ii++) { 52 | iters[ii].forEach(mergeIntoCollection); 53 | } 54 | }); 55 | } 56 | -------------------------------------------------------------------------------- /src/methods/mergeDeep.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { mergeDeepWithSources } from '../functional/merge'; 9 | 10 | export function mergeDeep(...iters) { 11 | return mergeDeepWithSources(this, iters); 12 | } 13 | 14 | export function mergeDeepWith(merger, ...iters) { 15 | return mergeDeepWithSources(this, iters, merger); 16 | } 17 | -------------------------------------------------------------------------------- /src/methods/mergeDeepIn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { mergeDeepWithSources } from '../functional/merge'; 9 | import { updateIn } from '../functional/updateIn'; 10 | import { emptyMap } from '../Map'; 11 | 12 | export function mergeDeepIn(keyPath, ...iters) { 13 | return updateIn(this, keyPath, emptyMap(), (m) => 14 | mergeDeepWithSources(m, iters) 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /src/methods/mergeIn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { mergeWithSources } from '../functional/merge'; 9 | import { updateIn } from '../functional/updateIn'; 10 | import { emptyMap } from '../Map'; 11 | 12 | export function mergeIn(keyPath, ...iters) { 13 | return updateIn(this, keyPath, emptyMap(), (m) => mergeWithSources(m, iters)); 14 | } 15 | -------------------------------------------------------------------------------- /src/methods/setIn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { setIn as _setIn } from '../functional/setIn'; 9 | 10 | export function setIn(keyPath, v) { 11 | return _setIn(this, keyPath, v); 12 | } 13 | -------------------------------------------------------------------------------- /src/methods/toObject.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import assertNotInfinite from '../utils/assertNotInfinite'; 9 | 10 | export function toObject() { 11 | assertNotInfinite(this.size); 12 | const object = {}; 13 | this.__iterate((v, k) => { 14 | object[k] = v; 15 | }); 16 | return object; 17 | } 18 | -------------------------------------------------------------------------------- /src/methods/update.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { update as _update } from '../functional/update'; 9 | 10 | export function update(key, notSetValue, updater) { 11 | return arguments.length === 1 12 | ? key(this) 13 | : _update(this, key, notSetValue, updater); 14 | } 15 | -------------------------------------------------------------------------------- /src/methods/updateIn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { updateIn as _updateIn } from '../functional/updateIn'; 9 | 10 | export function updateIn(keyPath, notSetValue, updater) { 11 | return _updateIn(this, keyPath, notSetValue, updater); 12 | } 13 | -------------------------------------------------------------------------------- /src/methods/wasAltered.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export function wasAltered() { 9 | return this.__altered; 10 | } 11 | -------------------------------------------------------------------------------- /src/methods/withMutations.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export function withMutations(fn) { 9 | const mutable = this.asMutable(); 10 | fn(mutable); 11 | return mutable.wasAltered() ? mutable.__ensureOwner(this.__ownerID) : this; 12 | } 13 | -------------------------------------------------------------------------------- /src/predicates/isAssociative.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { isKeyed } from './isKeyed'; 9 | import { isIndexed } from './isIndexed'; 10 | 11 | export function isAssociative(maybeAssociative) { 12 | return isKeyed(maybeAssociative) || isIndexed(maybeAssociative); 13 | } 14 | -------------------------------------------------------------------------------- /src/predicates/isCollection.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Note: value is unchanged to not break immutable-devtools. 9 | export const IS_COLLECTION_SYMBOL = '@@__IMMUTABLE_ITERABLE__@@'; 10 | 11 | export function isCollection(maybeCollection) { 12 | return Boolean(maybeCollection && maybeCollection[IS_COLLECTION_SYMBOL]); 13 | } 14 | -------------------------------------------------------------------------------- /src/predicates/isImmutable.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { isCollection } from './isCollection'; 9 | import { isRecord } from './isRecord'; 10 | 11 | export function isImmutable(maybeImmutable) { 12 | return isCollection(maybeImmutable) || isRecord(maybeImmutable); 13 | } 14 | -------------------------------------------------------------------------------- /src/predicates/isIndexed.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export const IS_INDEXED_SYMBOL = '@@__IMMUTABLE_INDEXED__@@'; 9 | 10 | export function isIndexed(maybeIndexed) { 11 | return Boolean(maybeIndexed && maybeIndexed[IS_INDEXED_SYMBOL]); 12 | } 13 | -------------------------------------------------------------------------------- /src/predicates/isKeyed.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export const IS_KEYED_SYMBOL = '@@__IMMUTABLE_KEYED__@@'; 9 | 10 | export function isKeyed(maybeKeyed) { 11 | return Boolean(maybeKeyed && maybeKeyed[IS_KEYED_SYMBOL]); 12 | } 13 | -------------------------------------------------------------------------------- /src/predicates/isList.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export const IS_LIST_SYMBOL = '@@__IMMUTABLE_LIST__@@'; 9 | 10 | export function isList(maybeList) { 11 | return Boolean(maybeList && maybeList[IS_LIST_SYMBOL]); 12 | } 13 | -------------------------------------------------------------------------------- /src/predicates/isMap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export const IS_MAP_SYMBOL = '@@__IMMUTABLE_MAP__@@'; 9 | 10 | export function isMap(maybeMap) { 11 | return Boolean(maybeMap && maybeMap[IS_MAP_SYMBOL]); 12 | } 13 | -------------------------------------------------------------------------------- /src/predicates/isOrdered.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export const IS_ORDERED_SYMBOL = '@@__IMMUTABLE_ORDERED__@@'; 9 | 10 | export function isOrdered(maybeOrdered) { 11 | return Boolean(maybeOrdered && maybeOrdered[IS_ORDERED_SYMBOL]); 12 | } 13 | -------------------------------------------------------------------------------- /src/predicates/isOrderedMap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { isMap } from './isMap'; 9 | import { isOrdered } from './isOrdered'; 10 | 11 | export function isOrderedMap(maybeOrderedMap) { 12 | return isMap(maybeOrderedMap) && isOrdered(maybeOrderedMap); 13 | } 14 | -------------------------------------------------------------------------------- /src/predicates/isOrderedSet.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { isSet } from './isSet'; 9 | import { isOrdered } from './isOrdered'; 10 | 11 | export function isOrderedSet(maybeOrderedSet) { 12 | return isSet(maybeOrderedSet) && isOrdered(maybeOrderedSet); 13 | } 14 | -------------------------------------------------------------------------------- /src/predicates/isRecord.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export const IS_RECORD_SYMBOL = '@@__IMMUTABLE_RECORD__@@'; 9 | 10 | export function isRecord(maybeRecord) { 11 | return Boolean(maybeRecord && maybeRecord[IS_RECORD_SYMBOL]); 12 | } 13 | -------------------------------------------------------------------------------- /src/predicates/isSeq.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export const IS_SEQ_SYMBOL = '@@__IMMUTABLE_SEQ__@@'; 9 | 10 | export function isSeq(maybeSeq) { 11 | return Boolean(maybeSeq && maybeSeq[IS_SEQ_SYMBOL]); 12 | } 13 | -------------------------------------------------------------------------------- /src/predicates/isSet.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export const IS_SET_SYMBOL = '@@__IMMUTABLE_SET__@@'; 9 | 10 | export function isSet(maybeSet) { 11 | return Boolean(maybeSet && maybeSet[IS_SET_SYMBOL]); 12 | } 13 | -------------------------------------------------------------------------------- /src/predicates/isStack.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export const IS_STACK_SYMBOL = '@@__IMMUTABLE_STACK__@@'; 9 | 10 | export function isStack(maybeStack) { 11 | return Boolean(maybeStack && maybeStack[IS_STACK_SYMBOL]); 12 | } 13 | -------------------------------------------------------------------------------- /src/predicates/isValueObject.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export function isValueObject(maybeValue) { 9 | return Boolean( 10 | maybeValue && 11 | typeof maybeValue.equals === 'function' && 12 | typeof maybeValue.hashCode === 'function' 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /src/toJS.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { Seq } from './Seq'; 9 | import { isCollection } from './predicates/isCollection'; 10 | import { isKeyed } from './predicates/isKeyed'; 11 | import isDataStructure from './utils/isDataStructure'; 12 | 13 | export function toJS(value) { 14 | if (!value || typeof value !== 'object') { 15 | return value; 16 | } 17 | if (!isCollection(value)) { 18 | if (!isDataStructure(value)) { 19 | return value; 20 | } 21 | value = Seq(value); 22 | } 23 | if (isKeyed(value)) { 24 | const result = {}; 25 | value.__iterate((v, k) => { 26 | result[k] = toJS(v); 27 | }); 28 | return result; 29 | } 30 | const result = []; 31 | value.__iterate((v) => { 32 | result.push(toJS(v)); 33 | }); 34 | return result; 35 | } 36 | -------------------------------------------------------------------------------- /src/utils/arrCopy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // http://jsperf.com/copy-array-inline 9 | export default function arrCopy(arr, offset) { 10 | offset = offset || 0; 11 | const len = Math.max(0, arr.length - offset); 12 | const newArr = new Array(len); 13 | for (let ii = 0; ii < len; ii++) { 14 | newArr[ii] = arr[ii + offset]; 15 | } 16 | return newArr; 17 | } 18 | -------------------------------------------------------------------------------- /src/utils/assertNotInfinite.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import invariant from './invariant'; 9 | 10 | export default function assertNotInfinite(size) { 11 | invariant( 12 | size !== Infinity, 13 | 'Cannot perform this action with an infinite size.' 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /src/utils/coerceKeyPath.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { isOrdered } from '../predicates/isOrdered'; 9 | import isArrayLike from './isArrayLike'; 10 | 11 | export default function coerceKeyPath(keyPath) { 12 | if (isArrayLike(keyPath) && typeof keyPath !== 'string') { 13 | return keyPath; 14 | } 15 | if (isOrdered(keyPath)) { 16 | return keyPath.toArray(); 17 | } 18 | throw new TypeError( 19 | 'Invalid keyPath: expected Ordered Collection or Array: ' + keyPath 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /src/utils/createClass.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export default function createClass(ctor, superClass) { 9 | if (superClass) { 10 | ctor.prototype = Object.create(superClass.prototype); 11 | } 12 | ctor.prototype.constructor = ctor; 13 | } 14 | -------------------------------------------------------------------------------- /src/utils/deepEqual.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { is } from '../is'; 9 | import { NOT_SET } from '../TrieUtils'; 10 | import { isCollection } from '../predicates/isCollection'; 11 | import { isKeyed } from '../predicates/isKeyed'; 12 | import { isIndexed } from '../predicates/isIndexed'; 13 | import { isAssociative } from '../predicates/isAssociative'; 14 | import { isOrdered } from '../predicates/isOrdered'; 15 | 16 | export default function deepEqual(a, b) { 17 | if (a === b) { 18 | return true; 19 | } 20 | 21 | if ( 22 | !isCollection(b) || 23 | (a.size !== undefined && b.size !== undefined && a.size !== b.size) || 24 | (a.__hash !== undefined && 25 | b.__hash !== undefined && 26 | a.__hash !== b.__hash) || 27 | isKeyed(a) !== isKeyed(b) || 28 | isIndexed(a) !== isIndexed(b) || 29 | isOrdered(a) !== isOrdered(b) 30 | ) { 31 | return false; 32 | } 33 | 34 | if (a.size === 0 && b.size === 0) { 35 | return true; 36 | } 37 | 38 | const notAssociative = !isAssociative(a); 39 | 40 | if (isOrdered(a)) { 41 | const entries = a.entries(); 42 | return ( 43 | b.every((v, k) => { 44 | const entry = entries.next().value; 45 | return entry && is(entry[1], v) && (notAssociative || is(entry[0], k)); 46 | }) && entries.next().done 47 | ); 48 | } 49 | 50 | let flipped = false; 51 | 52 | if (a.size === undefined) { 53 | if (b.size === undefined) { 54 | if (typeof a.cacheResult === 'function') { 55 | a.cacheResult(); 56 | } 57 | } else { 58 | flipped = true; 59 | const _ = a; 60 | a = b; 61 | b = _; 62 | } 63 | } 64 | 65 | let allEqual = true; 66 | const bSize = b.__iterate((v, k) => { 67 | if ( 68 | notAssociative 69 | ? !a.has(v) 70 | : flipped 71 | ? !is(v, a.get(k, NOT_SET)) 72 | : !is(a.get(k, NOT_SET), v) 73 | ) { 74 | allEqual = false; 75 | return false; 76 | } 77 | }); 78 | 79 | return allEqual && a.size === bSize; 80 | } 81 | -------------------------------------------------------------------------------- /src/utils/hasOwnProperty.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export default Object.prototype.hasOwnProperty; 9 | -------------------------------------------------------------------------------- /src/utils/invariant.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export default function invariant(condition, error) { 9 | if (!condition) throw new Error(error); 10 | } 11 | -------------------------------------------------------------------------------- /src/utils/isArrayLike.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | export default function isArrayLike(value) { 9 | if (Array.isArray(value) || typeof value === 'string') { 10 | return true; 11 | } 12 | 13 | return ( 14 | value && 15 | typeof value === 'object' && 16 | Number.isInteger(value.length) && 17 | value.length >= 0 && 18 | (value.length === 0 19 | ? // Only {length: 0} is considered Array-like. 20 | Object.keys(value).length === 1 21 | : // An object is only Array-like if it has a property where the last value 22 | // in the array-like may be found (which could be undefined). 23 | value.hasOwnProperty(value.length - 1)) 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /src/utils/isDataStructure.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { isImmutable } from '../predicates/isImmutable'; 9 | import isPlainObj from './isPlainObj'; 10 | 11 | /** 12 | * Returns true if the value is a potentially-persistent data structure, either 13 | * provided by Immutable.js or a plain Array or Object. 14 | */ 15 | export default function isDataStructure(value) { 16 | return ( 17 | typeof value === 'object' && 18 | (isImmutable(value) || Array.isArray(value) || isPlainObj(value)) 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /src/utils/isPlainObj.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const toString = Object.prototype.toString; 9 | 10 | export default function isPlainObject(value) { 11 | // The base prototype's toString deals with Argument objects and native namespaces like Math 12 | if ( 13 | !value || 14 | typeof value !== 'object' || 15 | toString.call(value) !== '[object Object]' 16 | ) { 17 | return false; 18 | } 19 | 20 | const proto = Object.getPrototypeOf(value); 21 | if (proto === null) { 22 | return true; 23 | } 24 | 25 | // Iteratively going up the prototype chain is needed for cross-realm environments (differing contexts, iframes, etc) 26 | let parentProto = proto; 27 | let nextProto = Object.getPrototypeOf(proto); 28 | while (nextProto !== null) { 29 | parentProto = nextProto; 30 | nextProto = Object.getPrototypeOf(parentProto); 31 | } 32 | return parentProto === proto; 33 | } 34 | -------------------------------------------------------------------------------- /src/utils/mixin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /** 9 | * Contributes additional methods to a constructor 10 | */ 11 | export default function mixin(ctor, methods) { 12 | const keyCopier = (key) => { 13 | ctor.prototype[key] = methods[key]; 14 | }; 15 | Object.keys(methods).forEach(keyCopier); 16 | Object.getOwnPropertySymbols && 17 | Object.getOwnPropertySymbols(methods).forEach(keyCopier); 18 | return ctor; 19 | } 20 | -------------------------------------------------------------------------------- /src/utils/quoteString.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /** 9 | * Converts a value to a string, adding quotes if a string was provided. 10 | */ 11 | export default function quoteString(value) { 12 | try { 13 | return typeof value === 'string' ? JSON.stringify(value) : String(value); 14 | } catch (_ignoreError) { 15 | return JSON.stringify(value); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/utils/shallowCopy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import arrCopy from './arrCopy'; 9 | import hasOwnProperty from './hasOwnProperty'; 10 | 11 | export default function shallowCopy(from) { 12 | if (Array.isArray(from)) { 13 | return arrCopy(from); 14 | } 15 | const to = {}; 16 | for (const key in from) { 17 | if (hasOwnProperty.call(from, key)) { 18 | to[key] = from[key]; 19 | } 20 | } 21 | return to; 22 | } 23 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint:recommended", "tslint-config-prettier"], 3 | "rules": { 4 | "array-type": [true, "generic"], 5 | "quotemark": false, 6 | "no-reference": false, 7 | "no-namespace": false, 8 | "member-access": false, 9 | "interface-name": false, 10 | "member-ordering": false, 11 | "only-arrow-functions": false, 12 | "object-literal-sort-keys": false, 13 | "no-conditional-assignment": false, 14 | "one-variable-per-declaration": false, 15 | "max-classes-per-file": false, 16 | "trailing-comma": [ 17 | true, 18 | { 19 | "multiline": { 20 | "objects": "always", 21 | "arrays": "always", 22 | "typeLiterals": "always", 23 | "functions": "never" 24 | } 25 | } 26 | ], 27 | "no-console": false 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /type-definitions/tests/.flowconfig: -------------------------------------------------------------------------------- 1 | [include] 2 | ../../ 3 | 4 | [options] 5 | suppress_comment=\\(.\\|\n\\)*\\$ExpectError 6 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe 7 | 8 | [ignore] 9 | 💩 Only interested in testing these files directly in this repo. 10 | .*/node_modules/.* 11 | -------------------------------------------------------------------------------- /type-definitions/tests/covariance.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @flow 8 | */ 9 | 10 | import { List, Map, Set, Stack, OrderedMap, OrderedSet } from '../../'; 11 | 12 | class A { 13 | x: number; 14 | } 15 | class B extends A { 16 | y: string; 17 | } 18 | class C { 19 | z: string; 20 | } 21 | 22 | // List covariance 23 | declare var listOfB: List; 24 | var listOfA: List = listOfB; 25 | listOfA = List([new B()]); 26 | // $ExpectError 27 | var listOfC: List = listOfB; 28 | 29 | // Map covariance 30 | declare var mapOfB: Map; 31 | var mapOfA: Map = mapOfB; 32 | mapOfA = Map({ b: new B() }); 33 | // $ExpectError 34 | var mapOfC: Map = mapOfB; 35 | 36 | // Set covariance 37 | declare var setOfB: Set; 38 | var setOfA: Set = setOfB; 39 | setOfA = Set([new B()]); 40 | // $ExpectError 41 | var setOfC: Set = setOfB; 42 | 43 | // Stack covariance 44 | declare var stackOfB: Stack; 45 | var stackOfA: Stack = stackOfB; 46 | stackOfA = Stack([new B()]); 47 | // $ExpectError 48 | var stackOfC: Stack = stackOfB; 49 | 50 | // OrderedMap covariance 51 | declare var orderedMapOfB: OrderedMap; 52 | var orderedMapOfA: OrderedMap = orderedMapOfB; 53 | orderedMapOfA = OrderedMap({ b: new B() }); 54 | // $ExpectError 55 | var orderedMapOfC: OrderedMap = orderedMapOfB; 56 | 57 | // OrderedSet covariance 58 | declare var orderedSetOfB: OrderedSet; 59 | var orderedSetOfA: OrderedSet = orderedSetOfB; 60 | orderedSetOfA = OrderedSet([new B()]); 61 | // $ExpectError 62 | var orderedSetOfC: OrderedSet = orderedSetOfB; 63 | -------------------------------------------------------------------------------- /type-definitions/tests/es6-collections.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @flow 8 | */ 9 | 10 | import { Map as ImmutableMap, Set as ImmutableSet } from '../../'; 11 | 12 | // Immutable.js collections 13 | var mapImmutable: ImmutableMap = ImmutableMap(); 14 | var setImmutable: ImmutableSet = ImmutableSet(); 15 | var deleteResultImmutable: ImmutableMap = mapImmutable.delete( 16 | 'foo' 17 | ); 18 | 19 | // ES6 collections 20 | var mapES6: Map = new Map(); 21 | var setES6: Set = new Set(); 22 | var deleteResultES6: boolean = mapES6.delete('foo'); 23 | -------------------------------------------------------------------------------- /type-definitions/tests/predicates.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @flow 8 | */ 9 | 10 | import { List } from '../../'; 11 | 12 | declare var mystery: mixed; 13 | 14 | // $ExpectError 15 | maybe.push('3'); 16 | 17 | if (mystery instanceof List) { 18 | maybe.push('3'); 19 | } 20 | 21 | // Note: Flow's support for %checks is still experimental. 22 | // Support this in the future. 23 | // if (List.isList(mystery)) { 24 | // mystery.push('3'); 25 | // } 26 | -------------------------------------------------------------------------------- /type-definitions/ts-tests/covariance.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { List, Map, OrderedMap, OrderedSet, Set, Stack } from '../../'; 9 | 10 | class A { 11 | x: number; 12 | } 13 | class B extends A { 14 | y: string; 15 | } 16 | class C { 17 | z: string; 18 | } 19 | 20 | // List covariance 21 | const listOfB: List = List(); 22 | let listOfA: List = listOfB; 23 | 24 | // $ExpectType List 25 | listOfA = List([new B()]); 26 | 27 | // $ExpectError 28 | const listOfC: List = listOfB; 29 | 30 | // Map covariance 31 | declare var mapOfB: Map; 32 | let mapOfA: Map = mapOfB; 33 | 34 | // $ExpectType Map 35 | mapOfA = Map({ b: new B() }); 36 | 37 | // $ExpectError 38 | const mapOfC: Map = mapOfB; 39 | 40 | // Set covariance 41 | declare var setOfB: Set; 42 | let setOfA: Set = setOfB; 43 | 44 | // $ExpectType Set 45 | setOfA = Set([new B()]); 46 | // $ExpectError 47 | const setOfC: Set = setOfB; 48 | 49 | // Stack covariance 50 | declare var stackOfB: Stack; 51 | let stackOfA: Stack = stackOfB; 52 | // $ExpectType Stack 53 | stackOfA = Stack([new B()]); 54 | // $ExpectError 55 | const stackOfC: Stack = stackOfB; 56 | 57 | // OrderedMap covariance 58 | declare var orderedMapOfB: OrderedMap; 59 | let orderedMapOfA: OrderedMap = orderedMapOfB; 60 | // $ExpectType OrderedMap 61 | orderedMapOfA = OrderedMap({ b: new B() }); 62 | // $ExpectError 63 | const orderedMapOfC: OrderedMap = orderedMapOfB; 64 | 65 | // OrderedSet covariance 66 | declare var orderedSetOfB: OrderedSet; 67 | let orderedSetOfA: OrderedSet = orderedSetOfB; 68 | // $ExpectType OrderedSet 69 | orderedSetOfA = OrderedSet([new B()]); 70 | // $ExpectError 71 | const orderedSetOfC: OrderedSet = orderedSetOfB; 72 | -------------------------------------------------------------------------------- /type-definitions/ts-tests/es6-collections.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { Map as ImmutableMap, Set as ImmutableSet } from '../../'; 9 | 10 | // Immutable.js collections 11 | const mapImmutable: ImmutableMap = ImmutableMap< 12 | string, 13 | number 14 | >(); 15 | const setImmutable: ImmutableSet = ImmutableSet(); 16 | 17 | // $ExpectType Map 18 | mapImmutable.delete('foo'); 19 | 20 | // ES6 collections 21 | const mapES6: Map = new Map(); 22 | const setES6: Set = new Set(); 23 | 24 | // $ExpectType boolean 25 | mapES6.delete('foo'); 26 | -------------------------------------------------------------------------------- /type-definitions/ts-tests/exports.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | // Some tests look like they are repeated in order to avoid false positives. 9 | 10 | import * as Immutable from '../../'; 11 | import { 12 | List, 13 | Map, 14 | OrderedMap, 15 | OrderedSet, 16 | Range, 17 | Repeat, 18 | Seq, 19 | Set, 20 | Stack, 21 | Collection, 22 | } from '../../'; 23 | 24 | List; // $ExpectType typeof List 25 | Map; // $ExpectType typeof Map 26 | OrderedMap; // $ExpectType typeof OrderedMap 27 | OrderedSet; // $ExpectType typeof OrderedSet 28 | // TODO: Turn on once https://github.com/Microsoft/dtslint/issues/19 is resolved. 29 | Range; // $ ExpectType (start?: number | undefined, end?: number | undefined, step?: number | undefined) => Indexed 30 | Repeat; // $ExpectType (value: T, times?: number | undefined) => Indexed 31 | Seq; // $ExpectType typeof Seq 32 | Set; // $ExpectType typeof Set 33 | Stack; // $ExpectType typeof Stack 34 | Collection; // $ExpectType typeof Collection 35 | Collection.Set; // $ExpectType (collection: Iterable) => Set 36 | Collection.Keyed; // $ ExpectType { (collection: Iterable<[K, V]>): Keyed; (obj: { [key: string]: V; }): Keyed } 37 | Collection.Indexed; // $ExpectType (collection: Iterable) => Indexed 38 | 39 | Immutable.List; // $ExpectType typeof List 40 | Immutable.Map; // $ExpectType typeof Map 41 | Immutable.OrderedMap; // $ExpectType typeof OrderedMap 42 | Immutable.OrderedSet; // $ExpectType typeof OrderedSet 43 | // TODO: Turn on once https://github.com/Microsoft/dtslint/issues/19 is resolved. 44 | Immutable.Range; // $ ExpectType (start?: number | undefined, end?: number | undefined, step?: number | undefined) => Indexed 45 | Immutable.Repeat; // $ExpectType (value: T, times?: number | undefined) => Indexed 46 | Immutable.Seq; // $ExpectType typeof Seq 47 | Immutable.Set; // $ExpectType typeof Set 48 | Immutable.Stack; // $ExpectType typeof Stack 49 | Immutable.Collection; // $ExpectType typeof Collection 50 | Immutable.Collection.Set; // $ExpectType (collection: Iterable) => Set 51 | Immutable.Collection.Keyed; // $ ExpectType { (collection: Iterable<[K, V]>): Keyed; (obj: { [key: string]: V; }): Keyed } 52 | Immutable.Collection.Indexed; // $ExpectType (collection: Iterable) => Indexed 53 | -------------------------------------------------------------------------------- /type-definitions/ts-tests/functional.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { get, has, set, remove, update } from '../../'; 9 | 10 | { 11 | // get 12 | 13 | // $ExpectType number | undefined 14 | get([1, 2, 3], 0); 15 | 16 | // $ExpectType number | "a" 17 | get([1, 2, 3], 0, 'a'); 18 | 19 | // $ExpectType number | undefined 20 | get({ x: 10, y: 20 }, 'x'); 21 | 22 | // $ExpectType number | "missing" 23 | get({ x: 10, y: 20 }, 'z', 'missing'); 24 | } 25 | 26 | { 27 | // has 28 | 29 | // $ExpectType boolean 30 | has([1, 2, 3], 0); 31 | 32 | // $ExpectType boolean 33 | has({ x: 10, y: 20 }, 'x'); 34 | } 35 | 36 | { 37 | // set 38 | 39 | // $ExpectType number[] 40 | set([1, 2, 3], 0, 10); 41 | 42 | // $ExpectError 43 | set([1, 2, 3], 0, 'a'); 44 | 45 | // $ExpectError 46 | set([1, 2, 3], 'a', 0); 47 | 48 | // $ExpectType { x: number; y: number; } 49 | set({ x: 10, y: 20 }, 'x', 100); 50 | 51 | // $ExpectError 52 | set({ x: 10, y: 20 }, 'x', 'a'); 53 | } 54 | 55 | { 56 | // remove 57 | 58 | // $ExpectType number[] 59 | remove([1, 2, 3], 0); 60 | 61 | // $ExpectType { x: number; y: number; } 62 | remove({ x: 10, y: 20 }, 'x'); 63 | } 64 | 65 | { 66 | // update 67 | 68 | // $ExpectType number[] 69 | update([1, 2, 3], 0, (v: number) => v + 1); 70 | 71 | // $ExpectError 72 | update([1, 2, 3], 0, 1); 73 | 74 | // $ExpectError 75 | update([1, 2, 3], 0, (v: string) => v + 'a'); 76 | 77 | // $ExpectError 78 | update([1, 2, 3], 'a', (v: number) => v + 1); 79 | 80 | // $ExpectType { x: number; y: number; } 81 | update({ x: 10, y: 20 }, 'x', (v: number) => v + 1); 82 | 83 | // $ExpectError 84 | update({ x: 10, y: 20 }, 'x', (v: string) => v + 'a'); 85 | } 86 | -------------------------------------------------------------------------------- /type-definitions/ts-tests/index.d.ts: -------------------------------------------------------------------------------- 1 | // TypeScript Version: 2.2 2 | /* tslint:disable:no-useless-files */ 3 | -------------------------------------------------------------------------------- /type-definitions/ts-tests/range.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { Range } from '../../'; 9 | 10 | { 11 | // #constructor 12 | 13 | // $ExpectType Indexed 14 | Range(0, 0, 0); 15 | 16 | // $ExpectError 17 | Range('a', 0, 0); 18 | } 19 | -------------------------------------------------------------------------------- /type-definitions/ts-tests/record.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { Record } from '../../'; 9 | 10 | { 11 | // Factory 12 | const PointXY = Record({ x: 0, y: 0 }); 13 | 14 | // $ExpectType Factory<{ x: number; y: number; }> 15 | PointXY; 16 | 17 | // $ExpectError 18 | PointXY({ x: 'a' }); 19 | 20 | const pointXY = PointXY(); 21 | 22 | // $ExpectType Record<{ x: number; y: number; }> & Readonly<{ x: number; y: number; }> 23 | pointXY; 24 | 25 | // $ExpectType number 26 | pointXY.x; 27 | 28 | // $ExpectError 29 | pointXY.x = 10; 30 | 31 | // $ExpectType number 32 | pointXY.y; 33 | 34 | // $ExpectError 35 | pointXY.y = 10; 36 | 37 | class PointClass extends PointXY { 38 | setX(x: number) { 39 | return this.set('x', x); 40 | } 41 | 42 | setY(y: number) { 43 | return this.set('y', y); 44 | } 45 | } 46 | 47 | const point = new PointClass(); 48 | 49 | // $ExpectType PointClass 50 | point; 51 | 52 | // $ExpectType number 53 | point.x; 54 | 55 | // $ExpectType number 56 | point.y; 57 | 58 | // $ExpectType PointClass 59 | point.setX(10); 60 | 61 | // $ExpectType PointClass 62 | point.setY(10); 63 | } 64 | 65 | { 66 | // .getDescriptiveName 67 | const PointXY = Record({ x: 0, y: 0 }); 68 | 69 | // $ExpectType string 70 | Record.getDescriptiveName(PointXY()); 71 | 72 | // $ExpectError 73 | Record.getDescriptiveName({}); 74 | } 75 | -------------------------------------------------------------------------------- /type-definitions/ts-tests/repeat.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { Repeat } from '../../'; 9 | 10 | { 11 | // #constructor 12 | 13 | // $ExpectType Indexed 14 | Repeat(0, 0); 15 | 16 | // $ExpectType Indexed 17 | Repeat('a', 0); 18 | 19 | // $ExpectError 20 | Repeat('a', 'b'); 21 | } 22 | -------------------------------------------------------------------------------- /type-definitions/ts-tests/seq.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2014-present, Facebook, Inc. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import { Seq } from '../../'; 9 | 10 | { 11 | // #constructor 12 | 13 | // $ExpectType Indexed 14 | Seq([1, 2, 3]); 15 | } 16 | 17 | { 18 | // #size 19 | 20 | // $ExpectType number | undefined 21 | Seq().size; 22 | 23 | // $ExpectError 24 | Seq().size = 10; 25 | } 26 | -------------------------------------------------------------------------------- /type-definitions/ts-tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "module": "commonjs", 5 | "sourceMap": true, 6 | "noImplicitAny": true, 7 | "noImplicitThis": true, 8 | "strictNullChecks": true, 9 | "strictFunctionTypes": true, 10 | "lib": ["es2015"], 11 | "types": [] 12 | }, 13 | "exclude": ["node_modules"] 14 | } 15 | -------------------------------------------------------------------------------- /type-definitions/ts-tests/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "dtslint/dtslint.json", 3 | "rules": { 4 | "no-var": false, 5 | "prefer-const": false, 6 | "no-useless-files": false, 7 | "no-duplicate-imports": false, 8 | "no-relative-import-in-test": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /type-definitions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "module": "commonjs", 5 | "sourceMap": true, 6 | "noImplicitAny": true, 7 | "noImplicitThis": true, 8 | "strictNullChecks": true, 9 | "strictFunctionTypes": true, 10 | "lib": ["es2015"], 11 | "types": [] 12 | }, 13 | "files": ["Immutable.d.ts"] 14 | } 15 | --------------------------------------------------------------------------------