pax_global_header00006660000000000000000000000064127440753120014517gustar00rootroot0000000000000052 comment=92391c8ec762e40426cdcc4c88af8177c036ca62 js-oolong-1.15.1/000077500000000000000000000000001274407531200135135ustar00rootroot00000000000000js-oolong-1.15.1/.gitignore000066400000000000000000000000341274407531200155000ustar00rootroot00000000000000/node_modules/ /*.tgz /tmp/ js-oolong-1.15.1/.npmignore000066400000000000000000000000321274407531200155050ustar00rootroot00000000000000/*.tgz /tmp/ /.travis.yml js-oolong-1.15.1/.travis.yml000066400000000000000000000002251274407531200156230ustar00rootroot00000000000000sudo: false language: node_js node_js: - "node" - "0.10" - "0.11" - "0.12" - "4" - "5" - "6" notifications: email: ["andri@dot.ee"] js-oolong-1.15.1/CHANGELOG.md000066400000000000000000000115341274407531200153300ustar00rootroot00000000000000## 1.15.1 (Jul 21, 2016) - Fixes [`Oolong.create`][create] to not mutate the prototype argument under global strict mode when given objects to assign to it. This affected only people running their JavaScript engine (like V8) under global strict mode (`--use-strict`), which seems very rare. ## 1.15.0 (Jul 15, 2016) - Adds [`Oolong.assignOwn`][assignOwn]. [assignOwn]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.assignOwn ## 1.14.1 (Nov 12, 2015) - Changes [`Oolong.pickDeep`][pickDeep] to take an array of keys (`["a", "b", "c"]`) instead of a string with embedded periods (`a.b.c`). As using periods initially was a brain fluke noticed shortly after releasing v1.14, increasing only the patch version number. ## 1.14.0 (Nov 12, 2015) - Adds [`Oolong.pick`][pick]. - Adds [`Oolong.pickDeep`][pickDeep]. [pick]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.pick [pickDeep]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.pickDeep ## 1.13.0 (Jul 24, 2015) - Adds [`Oolong.property`][property]. - Adds [`Oolong.object`][object]. - Adds [`Oolong.pluck`][pluck]. [property]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.property [object]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.object [pluck]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.pluck ## 1.12.0 (Jun 26, 2015) - Adds [`Oolong.setPrototypeOf`][setPrototypeOf]. [setPrototypeOf]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.setPrototypeOf ## 1.11.1 (Jun 24, 2015) - Fixes [`Oolong.isPlainObject`][isPlainObject] to return `false` for `Array.prototype`. JavaScript is a prototypical language after all and the prototype of an array is an array. ## 1.11.0 (Jun 14, 2015) - Adds [`Oolong.lookupGetter`][lookupGetter]. - Adds [`Oolong.lookupSetter`][lookupSetter]. [lookupGetter]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.lookupGetter [lookupSetter]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.lookupSetter ## 1.10.0 (Jun 12, 2015) - Adds [`Oolong.isObject`][isObject]. [isObject]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.isObject ## 1.9.0 (Jun 1, 2015) - Adds [`Oolong.wrap`][wrap]. [wrap]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.wrap ## 1.8.0 (May 29, 2015) - Adds [`Oolong.defineGetter`][defineGetter]. - Adds [`Oolong.defineSetter`][defineSetter]. [defineGetter]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.defineGetter [defineSetter]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.defineSetter ## 1.7.0 (Apr 15, 2015) - Renames Objectware to Oolong. ## 1.6.0 (Feb 19, 2015) - Adds [`Oolong.create`][create]. - Adds [`Oolong.defaults`][defaults]. [create]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.create [defaults]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.defaults ## 1.5.0 (Feb 10, 2015) - Adds [`Oolong.each`][each]. - Adds [`Oolong.eachOwn`][eachOwn]. - Adds [`Oolong.forEach`][forEach]. - Adds [`Oolong.forEachOwn`][forEachOwn]. - Adds [`Oolong.has`][has]. - Adds [`Oolong.hasOwn`][hasOwn]. - Adds [`Oolong.isInOwn`][isInOwn]. - Adds [`Oolong.isOwnEmpty`][isOwnEmpty]. - Adds [`Oolong.ownKeys`][ownKeys]. [each]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.each [eachOwn]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.eachOwn [forEach]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.forEach [forEachOwn]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.forEachOwn [has]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.has [hasOwn]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.hasOwn [isInOwn]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.isInOwn [isOwnEmpty]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.isOwnEmpty [ownKeys]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.ownKeys ## 1.4.0 (Feb 8, 2015) - Adds [`Oolong.reject`][reject]. [reject]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.reject ## 1.3.0 (Feb 8, 2015) - Adds [`Oolong.isIn`][isIn]. [isIn]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.isIn ## 1.2.0 (Feb 7, 2015) - Fixes [`Oolong.merge`][merge] to clone plain objects objects recursively. Previously in some cases it cloned objects shallowly. - Adds [`Oolong.cloneDeep`][cloneDeep]. [cloneDeep]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.cloneDeep ## 1.1.0 (Feb 7, 2015) - Adds [`Oolong.isPlainObject`][isPlainObject]. - Adds [`Oolong.merge`][merge]. [isPlainObject]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.isPlainObject [merge]: https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.merge ## 1.0.0 (Jan 13, 2015) - Perfectly objective. js-oolong-1.15.1/LICENSE000066400000000000000000000016501274407531200145220ustar00rootroot00000000000000Oolong.js Copyright (C) 2014– Andri Möll This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. Additional permission under the GNU Affero GPL version 3 section 7: If you modify this Program, or any covered work, by linking or combining it with other code, such other code is not for that reason alone subject to any of the requirements of the GNU Affero GPL version 3. In summary: - You can use this program for no cost. - You can use this program for both personal and commercial reasons. - You do not have to share your own program's code which uses this program. - You have to share modifications (e.g bug-fixes) you've made to this program. For the full copy of the GNU Affero General Public License see: http://www.gnu.org/licenses. js-oolong-1.15.1/Makefile000066400000000000000000000025761274407531200151650ustar00rootroot00000000000000NODE = node NODE_OPTS = --use-strict TEST_OPTS = # NOTE: Sorry, mocumentation is not yet published. MOCUMENT = ~/Documents/Mocumentation/bin/mocument MOCUMENT_OPTS = --type yui --title Oolong.js GITHUB_URL = https://github.com/moll/js-oolong love: @echo "Feel like makin' love." test: @$(NODE) $(NODE_OPTS) ./node_modules/.bin/_mocha -R dot $(TEST_OPTS) spec: @$(NODE) $(NODE_OPTS) ./node_modules/.bin/_mocha -R spec $(TEST_OPTS) autotest: @$(NODE) $(NODE_OPTS) ./node_modules/.bin/_mocha -R dot --watch $(TEST_OPTS) autospec: @$(NODE) $(NODE_OPTS) ./node_modules/.bin/_mocha -R spec --watch $(TEST_OPTS) pack: @file=$$(npm pack); echo "$$file"; tar tf "$$file" publish: npm publish tag: git tag "v$$($(NODE) -e 'console.log(require("./package").version)')" doc: doc.json @mkdir -p doc @$(MOCUMENT) $(MOCUMENT_OPTS) tmp/doc/data.json > doc/API.md toc: doc.json @$(MOCUMENT) $(MOCUMENT_OPTS) \ --template toc \ --var api_url=$(GITHUB_URL)/blob/master/doc/API.md \ tmp/doc/data.json > tmp/TOC.md @echo '/^API$$/,/^License$$/{/^API$$/{r tmp/TOC.md\na\\\n\\\n\\\n\n};/^License/!d;}' |\ sed -i "" -f /dev/stdin README.md doc.json: @mkdir -p tmp @yuidoc --exclude test,node_modules --parse-only --outdir tmp/doc . clean: rm -f *.tgz tmp npm prune --production .PHONY: love .PHONY: test spec autotest autospec .PHONY: pack publish tag .PHONY: doc toc doc.json .PHONY: clean js-oolong-1.15.1/README.md000066400000000000000000000143231274407531200147750ustar00rootroot00000000000000Oolong.js ========= [![NPM version][npm-badge]](https://www.npmjs.com/package/oolong) [![Build status][travis-badge]](https://travis-ci.org/moll/js-oolong) **Oolong.js** is a library for JavaScript full of **object-related utilities**. It's similar to [Underscore.js][underscore], but it focuses strictly on functions **dealing with objects**. It's implementation emphasizes **simplicity** and **good taste**. For example, it always **takes inherited properties** into account leading to less surprises for users of your code. **Oolong.js** grew out of my frustration with [Underscore.js][underscore] and [Lodash.js][lodash] and their inconsistent and sometimes outright ignorance of inherited properties. This leads to unnecessary complexity, arbitrary constraints and a leaky-implementation in your code or public APIs. This behavior is cancer propelled around by ignorance and misunderstandings between dictionaries and interfaces. Oolong.js is my first step at killing it. [npm-badge]: https://img.shields.io/npm/v/oolong.svg [travis-badge]: https://travis-ci.org/moll/js-oolong.png?branch=master [underscore]: https://underscorejs.org [lodash]: https://lodash.com Installing ---------- ```sh npm install oolong ``` Oolong.js follows [semantic versioning](http://semver.org/), so feel free to depend on its major version with something like `>= 1.0.0 < 2` (a.k.a `^1.0.0`). API --- For extended documentation on all functions, please see the [Oolong.js API Documentation][api]. [api]: https://github.com/moll/js-oolong/blob/master/doc/API.md ### [Oolong](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong) - [.assign](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.assign)(target, source...) - [.assignOwn](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.assignOwn)(target, source...) - [.clone](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.clone)(object) - [.cloneDeep](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.cloneDeep)(object) - [.create](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.create)(prototype, [source...]) - [.defaults](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.defaults)(target, source...) - [.defineGetter](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.defineGetter)(object, property, fn) - [.defineSetter](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.defineSetter)(object, property, fn) - [.each](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.each)(object, callback, [thisArg]) - [.eachOwn](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.eachOwn)(object, callback, [thisArg]) - [.filter](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.filter)(object, callback, [thisArg]) - [.forEach](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.forEach)(object, callback, [thisArg]) - [.forEachOwn](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.forEachOwn)(object, callback, [thisArg]) - [.has](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.has)(object, key) - [.hasOwn](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.hasOwn)(object, key) - [.isEmpty](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.isEmpty)(object) - [.isIn](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.isIn)(object, key) - [.isInOwn](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.isInOwn)(object, key) - [.isObject](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.isObject)(object) - [.isOwnEmpty](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.isOwnEmpty)(object) - [.isPlainObject](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.isPlainObject)(object) - [.keys](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.keys)(object) - [.lookupGetter](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.lookupGetter)(object, property) - [.lookupSetter](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.lookupSetter)(object, property) - [.map](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.map)(object, callback, [thisArg]) - [.mapKeys](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.mapKeys)(object, callback, [thisArg]) - [.merge](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.merge)(target, source...) - [.object](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.object)(keys, callback, [thisArg]) - [.ownKeys](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.ownKeys)(object) - [.pick](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.pick)(object, keys...) - [.pickDeep](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.pickDeep)(object, keys...) - [.pluck](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.pluck)(object, key) - [.property](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.property)(key) - [.reject](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.reject)(object, callback, [thisArg]) - [.setPrototypeOf](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.setPrototypeOf)(object, prototype) - [.values](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.values)(object) - [.wrap](https://github.com/moll/js-oolong/blob/master/doc/API.md#Oolong.wrap)(value, key) License ------- Oolong.js is released under a *Lesser GNU Affero General Public License*, which in summary means: - You **can** use this program for **no cost**. - You **can** use this program for **both personal and commercial reasons**. - You **do not have to share your own program's code** which uses this program. - You **have to share modifications** (e.g. bug-fixes) you've made to this program. For more convoluted language, see the `LICENSE` file. About ----- **[Andri Möll][moll]** typed this and the code. [Monday Calendar][monday] supported the engineering work. If you find Oolong.js needs improving, please don't hesitate to type to me now at [andri@dot.ee][email] or [create an issue online][issues]. [email]: mailto:andri@dot.ee [issues]: https://github.com/moll/js-oolong/issues [moll]: http://themoll.com [monday]: https://mondayapp.com js-oolong-1.15.1/doc/000077500000000000000000000000001274407531200142605ustar00rootroot00000000000000js-oolong-1.15.1/doc/API.md000066400000000000000000000415661274407531200152270ustar00rootroot00000000000000Oolong.js API Documentation =========================== ### [Oolong](#Oolong) - [.assign](#Oolong.assign)(target, source...) - [.assignOwn](#Oolong.assignOwn)(target, source...) - [.clone](#Oolong.clone)(object) - [.cloneDeep](#Oolong.cloneDeep)(object) - [.create](#Oolong.create)(prototype, [source...]) - [.defaults](#Oolong.defaults)(target, source...) - [.defineGetter](#Oolong.defineGetter)(object, property, fn) - [.defineSetter](#Oolong.defineSetter)(object, property, fn) - [.each](#Oolong.each)(object, callback, [thisArg]) - [.eachOwn](#Oolong.eachOwn)(object, callback, [thisArg]) - [.filter](#Oolong.filter)(object, callback, [thisArg]) - [.forEach](#Oolong.forEach)(object, callback, [thisArg]) - [.forEachOwn](#Oolong.forEachOwn)(object, callback, [thisArg]) - [.has](#Oolong.has)(object, key) - [.hasOwn](#Oolong.hasOwn)(object, key) - [.isEmpty](#Oolong.isEmpty)(object) - [.isIn](#Oolong.isIn)(object, key) - [.isInOwn](#Oolong.isInOwn)(object, key) - [.isObject](#Oolong.isObject)(object) - [.isOwnEmpty](#Oolong.isOwnEmpty)(object) - [.isPlainObject](#Oolong.isPlainObject)(object) - [.keys](#Oolong.keys)(object) - [.lookupGetter](#Oolong.lookupGetter)(object, property) - [.lookupSetter](#Oolong.lookupSetter)(object, property) - [.map](#Oolong.map)(object, callback, [thisArg]) - [.mapKeys](#Oolong.mapKeys)(object, callback, [thisArg]) - [.merge](#Oolong.merge)(target, source...) - [.object](#Oolong.object)(keys, callback, [thisArg]) - [.ownKeys](#Oolong.ownKeys)(object) - [.pick](#Oolong.pick)(object, keys...) - [.pickDeep](#Oolong.pickDeep)(object, keys...) - [.pluck](#Oolong.pluck)(object, key) - [.property](#Oolong.property)(key) - [.reject](#Oolong.reject)(object, callback, [thisArg]) - [.setPrototypeOf](#Oolong.setPrototypeOf)(object, prototype) - [.values](#Oolong.values)(object) - [.wrap](#Oolong.wrap)(value, key) Oolong ------ ### Oolong.assign(target, source...) Assigns all enumerable properties on `source` objects to `target`. Similar to `Object.assign`, but takes inherited properties into account. Does not modify anything in the source objects. Returns `target`. Think of it as _extending_ the first object step by step with others. **Examples**: ```javascript Oolong.assign({name: "John"}, {age: 32}, {shirt: "blue"}) // => {name: "John", age: 32, shirt: "blue"} ``` ### Oolong.assignOwn(target, source...) Assigns all own enumerable properties on `source` objects to `target`. Like `Object.assign`. Does not modify anything in the source objects. Returns `target`. Think of it as _extending_ the first object step by step with others. **Examples**: ```javascript Oolong.assignOwn({name: "John"}, {age: 32}, Object.create({shirt: "blue"})) // => {name: "John", age: 32} ``` ### Oolong.clone(object) Creates a shallow clone of the given object, taking all enumerable properties into account. Shallow means if you've got nested objects, those will be shared. **Examples**: ```javascript Oolong.clone({name: "John", age: 32}) // => {name: "John", age: 32} ``` ### Oolong.cloneDeep(object) Creates a deep clone of the given object, taking all enumerable properties into account. **Examples**: ```javascript Oolong.cloneDeep({name: "John", attributes: {age: 42}}) // => {name: "John", attributes: {age: 42}} ``` ### Oolong.create(prototype, [source...]) Creates and returns an object inheriting from `prototype` and, optionally, assigns enumerable properties from `source` objects to the new object. Uses `Object.create` and [`Oolong.assign`](#Oolong.assign) internally. Does not modify the given `prototype` nor source objects. **Examples**: ```javascript var PERSON = {name: "Unknown", age: 0} Oolong.create(PERSON, {name: "John"}, {shirt: "blue"}) // => {name: "John", age: 0, shirt: "blue"} ``` ### Oolong.defaults(target, source...) Assigns all enumerable properties on `source` objects to `target` that the `target` already _doesn't_ have. Uses `key in obj` to check for existence. Does not modify anything in the source objects. Returns `target`. Note that because **inherited properties** on `target` are checked, any property that exists on `Object.prototype` (e.g. `toString`, `valueOf`) will be skipped. Usually that's not a problem, but if you want to use `Oolong.defaults` for hashmaps/dictionaries with unknown keys, ensure `target` inherits from `null` instead (use `Object.create(null)`). **Examples**: ```javascript var PERSON = {name: "Unknown", age: 0, shirt: "blue"} Oolong.defaults({name: "John", age: 42}, PERSON) // => {name: "John", age: 42, shirt: "blue"} ``` ### Oolong.defineGetter(object, property, fn) Defines a getter on an object. Similar to [`Object.prototype.__defineGetter__`][__defineGetter__], but works in a standards compliant way. Returns `object`. The property is by default made *configurable* and *enumerable*. Should the property exist before, it's enumerability will be left as is. [__defineGetter__]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__defineGetter__ **Examples**: ```javascript var person = {birthyear: 1987} Oolong.defineGetter(person, "age", function() { return new Date().getFullYear() - this.birthyear }) person.age // => 28 as of today in 2015. ``` ### Oolong.defineSetter(object, property, fn) Defines a setter on an object. Similar to [`Object.prototype.__defineSetter__`][__defineSetter__], but works in a standards compliant way. Returns `object`. The property is by default made *configurable* and *enumerable*. Should the property exist before, it's enumerability will be left as is. [__defineSetter__]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__defineSetter__ **Examples**: ```javascript var person = {} Oolong.defineSetter(person, "age", function(age) { this.birthyear = new Date().getFullYear() - age }) person.age = 28 person.birthyear // => 1987 as of today in 2015. ``` ### Oolong.each(object, callback, [thisArg]) Calls the given function for all enumerable properties. Returns the given object. The function will be called with arguments `value`, `key` and `object` and bound to `thisArg`. **Examples**: ```javascript var obj = {name: "John", age: 42} Oolong.each(obj, function(val, key) { console.log(key + "=" + val) }) ``` ### Oolong.eachOwn(object, callback, [thisArg]) Calls the given function for all _own_ enumerable properties. Returns the given object. The function will be called with arguments `value`, `key` and `object` and bound to `thisArg`. **Examples**: ```javascript var obj = {name: "John", age: 42} Oolong.eachOwn(obj, function(val, key) { console.log(key + "=" + val) }) ``` ### Oolong.filter(object, callback, [thisArg]) Filters all enumerable properties and returns a new object with only those properties for which the given function returned truthy for. The function will be called with arguments `value`, `key` and `object` and bound to `thisArg`. **Examples**: ```javascript var obj = {a: 1, b: 2, c: 3, d: 4} Oolong.filter(obj, function(value, key) { return value % 2 == 0 }) // => {b: 2, d: 4} ``` ### Oolong.forEach(object, callback, [thisArg]) Alias of [`each`](#Oolong.each). ### Oolong.forEachOwn(object, callback, [thisArg]) Alias of [`eachOwn`](#Oolong.eachOwn). ### Oolong.has(object, key) Checks whether the given object has the given property, inherited or not. Given a set, but `undefined` property will still return `true`. **Examples**: ```javascript Oolong.has({name: "John"}) // => true Oolong.has(Object.create({name: "John"}), "name") // => true Oolong.has({}, "name") // => false ``` ### Oolong.hasOwn(object, key) Checks whether the given object has the given property as an own property. Given a set, but `undefined` property will still return `true`. **Examples**: ```javascript Oolong.hasOwn({name: "John"}) // => true Oolong.hasOwn(Object.create({name: "John"}), "name") // => false Oolong.hasOwn({}, "name") // => false ``` ### Oolong.isEmpty(object) Checks whether the given object has any enumerable properties, inherited or not. **Examples**: ```javascript Oolong.isEmpty({name: "John"}) // => false Oolong.isEmpty(Object.create({name: "John"})) // => false Oolong.isEmpty({}) // => true ``` ### Oolong.isIn(object, key) Alias of [`has`](#Oolong.has). ### Oolong.isInOwn(object, key) Alias of [`hasOwn`](#Oolong.hasOwn). ### Oolong.isObject(object) Checks whether the given object is of type object and is not null. **Examples**: ```javascript Oolong.isObject({name: "John"}) // => true Oolong.isObject(new Date) // => true Oolong.isObject(42) // => false Oolong.isObject(null) // => false ``` ### Oolong.isOwnEmpty(object) Checks whether the given object has any _own_ enumerable properties. **Examples**: ```javascript Oolong.isOwnEmpty({name: "John"}) // => false Oolong.isOwnEmpty(Object.create({name: "John"})) // => true Oolong.isOwnEmpty({}) // => true ``` ### Oolong.isPlainObject(object) Checks whether the given object is one constructed by `Object` or inheriting from `null`. A non-plain object has a `constructor` property set to anything but `Object`. That's the case when you do, for example, `new MyModel`, `new Date`. `Array.prototype` is not considered a plain object just like an array isn't a plain object. JavaScript is a prototypical language and the prototype of an array should be considered an array. **Examples**: ```javascript Oolong.isPlainObject({name: "John", age: 42}) // => true Oolong.isPlainObject(Object.create(null)) // => true Oolong.isPlainObject(Math) // => true Oolong.isPlainObject([]) // => false Oolong.isPlainObject(Array.prototype) // => false Oolong.isPlainObject(new Date) // => false Oolong.isPlainObject("John") // => false ``` ### Oolong.keys(object) Returns all enumerable keys of an object as an array. Similar to `Object.keys`, but takes inherited properties into account. **Examples**: ```javascript Oolong.keys({name: "John", age: 32}) // => ["name", "age"] ``` ### Oolong.lookupGetter(object, property) Looks up and returns a getter on an object. Similar to [`Object.prototype.__lookupGetter__`][__lookupGetter__], but works in a standards compliant way. Takes inherited getters into account, just like `__lookupGetter__`. [__lookupGetter__]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__lookupGetter__ **Examples**: ```javascript var person = {birthyear: 1987} Oolong.defineGetter(person, "age", function() { return new Date().getFullYear() - this.birthyear }) Oolong.lookupGetter(person, "age") // Returns the function above. ``` ### Oolong.lookupSetter(object, property) Looks up and returns a setter on an object. Similar to [`Object.prototype.__lookupSetter__`][__lookupSetter__], but works in a standards compliant way. Takes inherited setters into account, just like `__lookupSetter__`. [__lookupSetter__]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__lookupSetter__ **Examples**: ```javascript var person = {birthyear: 1987} Oolong.defineSetter(person, "age", function(age) { this.birthyear = new Date().getFullYear() - age }) Oolong.lookupSetter(person, "age") // Returns the function above. ``` ### Oolong.map(object, callback, [thisArg]) Maps all enumerable property values and returns a new object. The function will be called with arguments `value`, `key` and `object` and bound to `thisArg`. **Examples**: ```javascript var obj = {a: 1, b: 2, c: 3} Oolong.map(obj, function(value, key) { return value * 2 }) // => {a: 2, b: 4, c: 6} ``` ### Oolong.mapKeys(object, callback, [thisArg]) Transforms all enumerable keys and returns a new object. The function will be called with arguments `key`, `value` and `object` and bound to `thisArg`. **Examples**: ```javascript var person = {name: "John", age: 32} Oolong.mapKeys(person, function(key) { return key.toUpperCase() }) // => {NAME: "John", AGE: 32} ``` ### Oolong.merge(target, source...) Assigns all enumerable properties on `source` objects to `target` recursively. Only plain objects a merged. Refer to [`Oolong.isPlainObject`](#Oolong.isPlainObject) for the definition of a plain object. Does not modify anything in the source objects. Think of it as _extending_ the first object step by step with others. **Examples**: ```javascript var person = {name: "John", attributes: {age: 42}} Oolong.merge(person, {attributes: {height: 190}}) person // => {name: "John", attributes: {age: 42, height: 190}} ``` ### Oolong.object(keys, callback, [thisArg]) Returns a new object with keys taken from the array `keys` and values from the result of calling the given function with `key`, `index` and `keys`. It's like the reverse of indexing an array. **Examples**: ```javascript var names = ["Alice", "Bob", "Charlie"] var lengths = Oolong.object(names, function(name) { return name.length }) lengths // => {Alice: 5, Bob: 3, Charlie: 7} ``` ### Oolong.ownKeys(object) Returns all enumerable _own_ keys of an object as an array. Same as `Object.keys`, really. **Examples**: ```javascript var person = Object.create({name: "John"}) person.age = 42 Oolong.ownKeys(person) // => ["age"] ``` ### Oolong.pick(object, keys...) Filters the keys of an object to only those given as `keys...`. Only keys that exist in `object` are included. **Examples**: ```javascript var person = {name: "Alice", email: "alice@example.com", age: 42} Oolong.pick(person, "name", "age") // => {name: "Alice", age: 42} ``` ### Oolong.pickDeep(object, keys...) Filters the keys of an object to only those given as `keys...` with support for nested keys in an array (`["a", "b", "c"]`). Only keys that exist in `object` are included. If you'd like to use some other path syntax, feel free to preprocess your keys before passing them to `pickDeep`. For example, for a period-separated syntax (`a.b.c`), use a helper: ```javascript function path(s) { return s.split(".") } Oolong.pickDeep(person, "name", path("address.country")) ``` **Examples**: ```javascript var person = {name: "Alice", address: {country: "UK", street: "Downing"}} var obj = Oolong.pickDeep(person, "name", ["address", "country"]) obj // => {name: "Alice", address: {country: "UK"}} ``` ### Oolong.pluck(object, key) Returns a new object with the same keys, but with values being the value's property `key`. In other words, it's the same as `Oolong.map(obj, Oolong.property(key))`. **Examples**: ```javascript var people = { a: {name: "Alice"}, b: {name: "Bob"}, c: {name: "Charlie"} } Oolong.pluck(people, "name") // => {a: "Alice", b: "Bob", c: "Charlie"} ``` ### Oolong.property(key) Returns a function that returns the given property of an object. **Examples**: ```javascript var getName = Oolong.property("name") getName({name: "John"}) // => "John ``` ### Oolong.reject(object, callback, [thisArg]) Rejects all enumerable properties and returns a new object without those properties for which the given function returned truthy for. Opposite of [`filter`](#Oolong.filter). The function will be called with arguments `value`, `key` and `object` and bound to `thisArg`. **Examples**: ```javascript var obj = {a: 1, b: 2, c: 3, d: 4} Oolong.reject(obj, function(value, key) { return value % 2 == 0 }) // => {a: 1, c: 3} ``` ### Oolong.setPrototypeOf(object, prototype) Set the prototype of the given object to the given prototype. Pass `null` or another object for the prototype. Returns `object`. Uses `Object.setPrototypeOf` if it exists. Otherwise uses a polyfill. **Examples**: ```javascript var person = {name: "Unnamed", age: 42} var mike = Oolong.setPrototypeOf({name: "Mike"}, person) mike.name // => "Mike mike.age // => 42 ``` ### Oolong.values(object) Returns all enumerable property values as an array. **Examples**: ```javascript Oolong.values({name: "John", age: 32}) // => ["John", 32] ``` ### Oolong.wrap(value, key) Wraps a given value in an object under the specified key. Works also with [ECMAScript 6 Symbol](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Symbol). **Examples**: ```javascript Oolong.wrap("John", "name") // => {name: "John"} ``` js-oolong-1.15.1/index.js000066400000000000000000000530261274407531200151660ustar00rootroot00000000000000var hasOwn = Function.call.bind(Object.hasOwnProperty) var isEnumerable = Function.call.bind(Object.propertyIsEnumerable) var getPropertyDescriptor = require("./lib/es6").getPropertyDescriptor var lookupGetter = Object.prototype.__lookupGetter__ var lookupSetter = Object.prototype.__lookupSetter__ var isArray = Array.isArray var SET_PROTO_OF_NULL = "Oolong.setPrototypeOf called on null or undefined" /** * @class Oolong */ /** * Assigns all enumerable properties on `source` objects to `target`. * Similar to `Object.assign`, but takes inherited properties into account. * Does not modify anything in the source objects. * Returns `target`. * * Think of it as _extending_ the first object step by step with others. * * @example * Oolong.assign({name: "John"}, {age: 32}, {shirt: "blue"}) * // => {name: "John", age: 32, shirt: "blue"} * * @static * @method assign * @param target * @param source... */ exports.assign = function assign(target) { if (target != null) for (var i = 1; i < arguments.length; ++i) { var source = arguments[i] for (var key in source) target[key] = source[key] } return target } /** * Assigns all own enumerable properties on `source` objects to `target`. * Like `Object.assign`. Does not modify anything in the source objects. * Returns `target`. * * Think of it as _extending_ the first object step by step with others. * * @example * Oolong.assignOwn({name: "John"}, {age: 32}, Object.create({shirt: "blue"})) * // => {name: "John", age: 32} * * @static * @method assignOwn * @param target * @param source... */ exports.assignOwn = function assignOwn(target) { if (target != null) for (var i = 1; i < arguments.length; ++i) { var source = arguments[i] for (var key in source) if (hasOwn(source, key)) target[key] = source[key] } return target } /** * Creates a shallow clone of the given object, taking all enumerable * properties into account. * Shallow means if you've got nested objects, those will be shared. * * @example * Oolong.clone({name: "John", age: 32}) * // => {name: "John", age: 32} * * @static * @method clone * @param object */ exports.clone = function clone(obj) { return obj == null ? obj : exports.assign({}, obj) } /** * Creates a deep clone of the given object, taking all enumerable properties * into account. * * @example * Oolong.cloneDeep({name: "John", attributes: {age: 42}}) * // => {name: "John", attributes: {age: 42}} * * @static * @method cloneDeep * @param object */ exports.cloneDeep = function cloneDeep(obj) { return obj == null ? obj : exports.merge({}, obj) } /** * Creates and returns an object inheriting from `prototype` and, optionally, * assigns enumerable properties from `source` objects to the new object. * Uses `Object.create` and [`Oolong.assign`](#Oolong.assign) * internally. * Does not modify the given `prototype` nor source objects. * * @example * var PERSON = {name: "Unknown", age: 0} * Oolong.create(PERSON, {name: "John"}, {shirt: "blue"}) * // => {name: "John", age: 0, shirt: "blue"} * * @static * @method create * @param prototype * @param [source...] */ exports.create = function create(obj) { obj = arguments[0] = Object.create(obj) return arguments.length == 1 ? obj : exports.assign.apply(this, arguments) } /** * Assigns all enumerable properties on `source` objects to `target` that the * `target` already _doesn't_ have. Uses `key in obj` to check for existence. * Does not modify anything in the source objects. * Returns `target`. * * Note that because **inherited properties** on `target` are checked, any * property that exists on `Object.prototype` (e.g. `toString`, `valueOf`) * will be skipped. Usually that's not a problem, but if you want to use * `Oolong.defaults` for hashmaps/dictionaries with unknown keys, ensure * `target` inherits from `null` instead (use `Object.create(null)`). * * @example * var PERSON = {name: "Unknown", age: 0, shirt: "blue"} * Oolong.defaults({name: "John", age: 42}, PERSON) * // => {name: "John", age: 42, shirt: "blue"} * * @static * @method defaults * @param target * @param source... */ exports.defaults = function defaults(target) { if (target != null) for (var i = 1; i < arguments.length; ++i) { var source = arguments[i] for (var key in source) if (!(key in target)) target[key] = source[key] } return target } /** * Defines a getter on an object. * Similar to [`Object.prototype.__defineGetter__`][__defineGetter__], but * works in a standards compliant way. * Returns `object`. * * The property is by default made *configurable* and *enumerable*. Should the * property exist before, it's enumerability will be left as is. * * [__defineGetter__]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__defineGetter__ * * @example * var person = {birthyear: 1987} * * Oolong.defineGetter(person, "age", function() { * return new Date().getFullYear() - this.birthyear * }) * * person.age // => 28 as of today in 2015. * * @static * @method defineGetter * @param object * @param property * @param fn */ exports.defineGetter = function defineGetter(obj, name, fn) { return Object.defineProperty(obj, name, { get: fn, configurable: true, enumerable: !hasOwn(obj, name) || isEnumerable(obj, name) }) } /** * Defines a setter on an object. * Similar to [`Object.prototype.__defineSetter__`][__defineSetter__], but * works in a standards compliant way. * Returns `object`. * * The property is by default made *configurable* and *enumerable*. Should the * property exist before, it's enumerability will be left as is. * * [__defineSetter__]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__defineSetter__ * * @example * var person = {} * * Oolong.defineSetter(person, "age", function(age) { * this.birthyear = new Date().getFullYear() - age * }) * * person.age = 28 * person.birthyear // => 1987 as of today in 2015. * * @static * @method defineSetter * @param object * @param property * @param fn */ exports.defineSetter = function defineSetter(obj, name, fn) { return Object.defineProperty(obj, name, { set: fn, configurable: true, enumerable: !hasOwn(obj, name) || isEnumerable(obj, name) }) } /** * Calls the given function for all enumerable properties. * Returns the given object. * * The function will be called with arguments `value`, `key` and `object` and * bound to `thisArg`. * * @example * var obj = {name: "John", age: 42} * Oolong.each(obj, function(val, key) { console.log(key + "=" + val) }) * * @static * @method each * @param object * @param callback * @param [thisArg] */ exports.each = function each(obj, fn, context) { for (var key in obj) fn.call(context, obj[key], key, obj) return obj } /** * Calls the given function for all _own_ enumerable properties. * Returns the given object. * * The function will be called with arguments `value`, `key` and `object` and * bound to `thisArg`. * * @example * var obj = {name: "John", age: 42} * Oolong.eachOwn(obj, function(val, key) { console.log(key + "=" + val) }) * * @static * @method eachOwn * @param object * @param callback * @param [thisArg] */ exports.eachOwn = function eachOwn(obj, fn, context) { for (var key in obj) if (hasOwn(obj, key)) fn.call(context, obj[key], key, obj) return obj } /** * Filters all enumerable properties and returns a new object with only those * properties for which the given function returned truthy for. * * The function will be called with arguments `value`, `key` and `object` and * bound to `thisArg`. * * @example * var obj = {a: 1, b: 2, c: 3, d: 4} * Oolong.filter(obj, function(value, key) { return value % 2 == 0 }) * // => {b: 2, d: 4} * * @static * @method filter * @param object * @param callback * @param [thisArg] */ exports.filter = function filter(obj, fn, context) { var filtered = {} for (var key in obj) { var value = obj[key] if (fn.call(context, value, key, obj)) filtered[key] = value } return filtered } /** * @static * @method forEach * @alias each */ exports.forEach = exports.each /** * @static * @method forEachOwn * @alias eachOwn */ exports.forEachOwn = exports.eachOwn /** * Checks whether the given object has the given property, inherited or not. * Given a set, but `undefined` property will still return `true`. * * @example * Oolong.has({name: "John"}) // => true * Oolong.has(Object.create({name: "John"}), "name") // => true * Oolong.has({}, "name") // => false * * @static * @method has * @param object * @param key */ exports.has = function has(obj, key) { return key in obj } /** * Checks whether the given object has the given property as an own property. * Given a set, but `undefined` property will still return `true`. * * @example * Oolong.hasOwn({name: "John"}) // => true * Oolong.hasOwn(Object.create({name: "John"}), "name") // => false * Oolong.hasOwn({}, "name") // => false * * @static * @method hasOwn * @param object * @param key */ exports.hasOwn = hasOwn /** * Checks whether the given object has any enumerable properties, inherited * or not. * * @example * Oolong.isEmpty({name: "John"}) // => false * Oolong.isEmpty(Object.create({name: "John"})) // => false * Oolong.isEmpty({}) // => true * * @static * @method isEmpty * @param object */ exports.isEmpty = function isEmpty(obj) { for (obj in obj) return false return true } /** * @static * @method isIn * @alias has */ exports.isIn = exports.has /** * @static * @method isInOwn * @alias hasOwn */ exports.isInOwn = exports.hasOwn /** * Checks whether the given object is of type object and is not null. * * @example * Oolong.isObject({name: "John"}) // => true * Oolong.isObject(new Date) // => true * Oolong.isObject(42) // => false * Oolong.isObject(null) // => false * * @static * @method isObject * @param object */ exports.isObject = function isObject(obj) { return obj != null && typeof obj == "object" } /** * Checks whether the given object has any _own_ enumerable properties. * * @example * Oolong.isOwnEmpty({name: "John"}) // => false * Oolong.isOwnEmpty(Object.create({name: "John"})) // => true * Oolong.isOwnEmpty({}) // => true * * @static * @method isOwnEmpty * @param object */ exports.isOwnEmpty = function isOwnEmpty(obj) { for (var key in obj) if (hasOwn(obj, key)) return false return true } /** * Checks whether the given object is one constructed by `Object` or inheriting * from `null`. * * A non-plain object has a `constructor` property set to anything but `Object`. * That's the case when you do, for example, `new MyModel`, `new Date`. * * `Array.prototype` is not considered a plain object just like an array isn't * a plain object. JavaScript is a prototypical language and the prototype of * an array should be considered an array. * * @example * Oolong.isPlainObject({name: "John", age: 42}) // => true * Oolong.isPlainObject(Object.create(null)) // => true * Oolong.isPlainObject(Math) // => true * Oolong.isPlainObject([]) // => false * Oolong.isPlainObject(Array.prototype) // => false * Oolong.isPlainObject(new Date) // => false * Oolong.isPlainObject("John") // => false * * @static * @method isPlainObject * @param object */ exports.isPlainObject = function isPlainObject(obj) { if (obj == null) return false if (typeof obj != "object") return false if (isArray(obj)) return false var prototype = Object.getPrototypeOf(obj) if (prototype === null) return true if (!("constructor" in prototype)) return true return prototype.constructor === Object } /** * Returns all enumerable keys of an object as an array. * Similar to `Object.keys`, but takes inherited properties into account. * * @example * Oolong.keys({name: "John", age: 32}) // => ["name", "age"] * * @static * @method keys * @param object */ exports.keys = function keys(obj) { var keys = [] for (var key in obj) keys.push(key) return keys } /** * Looks up and returns a getter on an object. * Similar to [`Object.prototype.__lookupGetter__`][__lookupGetter__], but * works in a standards compliant way. * Takes inherited getters into account, just like `__lookupGetter__`. * * [__lookupGetter__]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__lookupGetter__ * * @example * var person = {birthyear: 1987} * * Oolong.defineGetter(person, "age", function() { * return new Date().getFullYear() - this.birthyear * }) * * Oolong.lookupGetter(person, "age") // Returns the function above. * * @static * @method lookupGetter * @param object * @param property */ exports.lookupGetter = lookupGetter ? Function.call.bind(lookupGetter) : function lookupSetter(obj, name) { var desc = getPropertyDescriptor(obj, name) return desc && desc.get } /** * Looks up and returns a setter on an object. * Similar to [`Object.prototype.__lookupSetter__`][__lookupSetter__], but * works in a standards compliant way. * Takes inherited setters into account, just like `__lookupSetter__`. * * [__lookupSetter__]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__lookupSetter__ * * @example * var person = {birthyear: 1987} * * Oolong.defineSetter(person, "age", function(age) { * this.birthyear = new Date().getFullYear() - age * }) * * Oolong.lookupSetter(person, "age") // Returns the function above. * * @static * @method lookupSetter * @param object * @param property */ exports.lookupSetter = lookupSetter ? Function.call.bind(lookupSetter) : function lookupSetter(obj, name) { var desc = getPropertyDescriptor(obj, name) return desc && desc.set } /** * Maps all enumerable property values and returns a new object. * * The function will be called with arguments `value`, `key` and `object` and * bound to `thisArg`. * * @example * var obj = {a: 1, b: 2, c: 3} * Oolong.map(obj, function(value, key) { return value * 2 }) * // => {a: 2, b: 4, c: 6} * * @static * @method map * @param object * @param callback * @param [thisArg] */ exports.map = function map(obj, fn, context) { var mapped = {} for (var key in obj) mapped[key] = fn.call(context, obj[key], key, obj) return mapped } /** * Transforms all enumerable keys and returns a new object. * * The function will be called with arguments `key`, `value` and `object` and * bound to `thisArg`. * * @example * var person = {name: "John", age: 32} * Oolong.mapKeys(person, function(key) { return key.toUpperCase() }) * // => {NAME: "John", AGE: 32} * * @static * @method mapKeys * @param object * @param callback * @param [thisArg] */ exports.mapKeys = function mapKeys(obj, fn, context) { var result = {} for (var key in obj) { var value = obj[key] result[fn.call(context, key, value, obj)] = value } return result } /** * Assigns all enumerable properties on `source` objects to `target` * recursively. * Only plain objects a merged. Refer to * [`Oolong.isPlainObject`](#Oolong.isPlainObject) for the definition of * a plain object. Does not modify anything in the source objects. * * Think of it as _extending_ the first object step by step with others. * * @example * var person = {name: "John", attributes: {age: 42}} * Oolong.merge(person, {attributes: {height: 190}}) * person // => {name: "John", attributes: {age: 42, height: 190}} * * @static * @method merge * @param target * @param source... */ exports.merge = function merge(target) { if (target != null) for (var i = 1; i < arguments.length; ++i) { var source = arguments[i] for (var key in source) { var a = target[key] var b = source[key] var aIsObject = exports.isPlainObject(a) var bIsObject = exports.isPlainObject(b) if (aIsObject && bIsObject) merge(a, b) else if (bIsObject) target[key] = merge({}, b) else target[key] = b } } return target } /** * Returns a new object with keys taken from the array `keys` and values * from the result of calling the given function with `key`, `index` and * `keys`. * It's like the reverse of indexing an array. * * @example * var names = ["Alice", "Bob", "Charlie"] * var lengths = Oolong.object(names, function(name) { return name.length }) * lengths // => {Alice: 5, Bob: 3, Charlie: 7} * * @static * @method object * @param keys * @param callback * @param [thisArg] */ exports.object = function object(keys, fn, thisArg) { var obj = {} for (var i = 0; i < keys.length; ++i) { var key = keys[i] obj[key] = fn.call(thisArg, key, i, keys) } return obj } /** * Returns all enumerable _own_ keys of an object as an array. * Same as `Object.keys`, really. * * @example * var person = Object.create({name: "John"}) * person.age = 42 * Oolong.ownKeys(person) // => ["age"] * * @static * @method ownKeys * @param object */ exports.ownKeys = Object.keys /** * Filters the keys of an object to only those given as `keys...`. * Only keys that exist in `object` are included. * * @example * var person = {name: "Alice", email: "alice@example.com", age: 42} * Oolong.pick(person, "name", "age") // => {name: "Alice", age: 42} * * @static * @method pick * @param object * @param keys... * */ exports.pick = function pick(obj) { var target = {} for (var i = 1; i < arguments.length; ++i) { var key = arguments[i] if (key in obj) target[key] = obj[key] } return target } /** * Filters the keys of an object to only those given as `keys...` with support * for nested keys in an array (`["a", "b", "c"]`). * Only keys that exist in `object` are included. * * If you'd like to use some other path syntax, feel free to preprocess your * keys before passing them to `pickDeep`. For example, for a period-separated * syntax (`a.b.c`), use a helper: * * ```javascript * function path(s) { return s.split(".") } * Oolong.pickDeep(person, "name", path("address.country")) * ``` * * @example * var person = {name: "Alice", address: {country: "UK", street: "Downing"}} * var obj = Oolong.pickDeep(person, "name", ["address", "country"]) * obj // => {name: "Alice", address: {country: "UK"}} * * @static * @method pickDeep * @param object * @param keys... * */ exports.pickDeep = function pickDeep(obj) { var target = {} for (var i = 1; i < arguments.length; ++i) { var keys = arrayify(arguments[i]), length = keys.length var key, value = obj, t = target, j for (j = 0; j < length && (key = keys[j]) in value; ++j) value = value[key] if (j !== length) continue for (j = 0; j < length - 1; ++j) t = t[keys[j]] || (t[keys[j]] = {}) t[keys[j]] = value } return target } /** * Returns a new object with the same keys, but with values being the value's * property `key`. * In other words, it's the same as `Oolong.map(obj, Oolong.property(key))`. * * @example * var people = { * a: {name: "Alice"}, * b: {name: "Bob"}, * c: {name: "Charlie"} * } * * Oolong.pluck(people, "name") // => {a: "Alice", b: "Bob", c: "Charlie"} * * @static * @method pluck * @param object * @param key */ exports.pluck = function pluck(obj, key) { return exports.map(obj, exports.property(key)) } /** * Returns a function that returns the given property of an object. * * @example * var getName = Oolong.property("name") * getName({name: "John"}) // => "John * * @static * @method property * @param key */ exports.property = function property(key) { return function(obj) { return obj[key] } } /** * Rejects all enumerable properties and returns a new object without those * properties for which the given function returned truthy for. * Opposite of [`filter`](#Oolong.filter). * * The function will be called with arguments `value`, `key` and `object` and * bound to `thisArg`. * * @example * var obj = {a: 1, b: 2, c: 3, d: 4} * Oolong.reject(obj, function(value, key) { return value % 2 == 0 }) * // => {a: 1, c: 3} * * @static * @method reject * @param object * @param callback * @param [thisArg] */ exports.reject = function reject(obj, fn, context) { return exports.filter(obj, not(fn), context) } /** * Set the prototype of the given object to the given prototype. * Pass `null` or another object for the prototype. * Returns `object`. * * Uses `Object.setPrototypeOf` if it exists. Otherwise uses a polyfill. * * @example * var person = {name: "Unnamed", age: 42} * var mike = Oolong.setPrototypeOf({name: "Mike"}, person) * mike.name // => "Mike * mike.age // => 42 * * @static * @method setPrototypeOf * @param object * @param prototype */ exports.setPrototypeOf = Object.setPrototypeOf || function setPrototypeOf(obj, prototype) { /* eslint no-proto: 0 */ if (obj == null) throw new TypeError(SET_PROTO_OF_NULL) if (typeof obj == "object") obj.__proto__ = prototype return obj } /** * Returns all enumerable property values as an array. * * @example * Oolong.values({name: "John", age: 32}) // => ["John", 32] * * @static * @method values * @param object */ exports.values = function values(obj) { var values = [] for (var key in obj) values.push(obj[key]) return values } /** * Wraps a given value in an object under the specified key. * Works also with [ECMAScript 6 Symbol](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Symbol). * * @example * Oolong.wrap("John", "name") // => {name: "John"} * * @static * @method wrap * @param value * @param key */ exports.wrap = function wrap(value, key) { var obj = {} obj[key] = value return obj } function not(fn) { return function() { return !fn.apply(this, arguments) }} function arrayify(value) { return isArray(value) ? value : [value] } js-oolong-1.15.1/lib/000077500000000000000000000000001274407531200142615ustar00rootroot00000000000000js-oolong-1.15.1/lib/es6.js000066400000000000000000000003721274407531200153160ustar00rootroot00000000000000exports.getPropertyDescriptor = Object.getPropertyDescriptor || function(obj, name) { if (!(name in obj)) return var desc do { if (desc = Object.getOwnPropertyDescriptor(obj, name)) return desc } while (obj = Object.getPrototypeOf(obj)) } js-oolong-1.15.1/package.json000066400000000000000000000014171274407531200160040ustar00rootroot00000000000000{ "name": "oolong", "version": "1.15.1", "description": "Utilities for objects. Simple, tasteful and plentiful. Supports inherited properties.", "keywords": [ "functional", "underscore", "util" ], "homepage": "https://github.com/moll/js-oolong", "bugs": "https://github.com/moll/js-oolong/issues", "author": { "name": "Andri Möll", "email": "andri@dot.ee", "url": "http://themoll.com" }, "repository": { "type": "git", "url": "git://github.com/moll/js-oolong.git" }, "licenses": [{ "type": "LAGPL", "url": "https://github.com/moll/js-oolong/blob/master/LICENSE" }], "main": "index.js", "scripts": {"test": "make test NODE_OPTS="}, "devDependencies": { "mocha": ">= 2.5.3 < 3", "must": ">= 0.13.2 < 0.14", "sinon": ">= 1.10.3 < 2" } } js-oolong-1.15.1/test/000077500000000000000000000000001274407531200144725ustar00rootroot00000000000000js-oolong-1.15.1/test/mocha.opts000066400000000000000000000000511274407531200164640ustar00rootroot00000000000000--recursive --require must --check-leaks js-oolong-1.15.1/test/oolong/000077500000000000000000000000001274407531200157675ustar00rootroot00000000000000js-oolong-1.15.1/test/oolong/assign_own_test.js000066400000000000000000000034661274407531200215440ustar00rootroot00000000000000var O = require("../..") var demand = require("must") describe("Oolong.assignOwn", function() { it("must return undefined given nothing", function() { demand(O.assignOwn()).be.undefined() }) it("must return null given null", function() { demand(O.assignOwn(null)).be.null() }) it("must return undefined given undefined and a source", function() { demand(O.assignOwn(undefined, {name: "John"})).be.undefined() }) it("must return null given null and a source", function() { demand(O.assignOwn(null, {name: "John"})).be.null() }) it("must return target given no source", function() { var obj = {} O.assignOwn(obj).must.equal(obj) }) it("must return target given one source", function() { var obj = {} O.assignOwn(obj, {name: "John"}).must.equal(obj) }) it("must assign properties to target from one source", function() { O.assignOwn({}, {name: "John"}).must.eql({name: "John"}) }) it("must assign properties to target from two sources", function() { O.assignOwn({}, {name: "John"}, {age: 13}).must.eql({name: "John", age: 13}) }) it("must overwrite property with later source", function() { O.assignOwn({}, {name: "John"}, {name: "Mike"}).must.eql({name: "Mike"}) }) it("must not change target given no source", function() { O.assignOwn({name: "John"}).must.eql({name: "John"}) }) it("must not assign properties from inherited sources", function() { O.assignOwn({}, Object.create({name: "John"})).must.eql({}) }) it("must not assign unenumerable properties", function() { var source = Object.defineProperty({}, "name", {value: "John"}) O.assignOwn({}, source).must.eql({}) }) it("must assign properties with undefined value", function() { O.assignOwn({name: "John"}, {name: undefined}).must.eql({name: undefined}) }) }) js-oolong-1.15.1/test/oolong/assign_test.js000066400000000000000000000034241274407531200206530ustar00rootroot00000000000000var O = require("../..") var demand = require("must") describe("Oolong.assign", function() { it("must return undefined given nothing", function() { demand(O.assign()).be.undefined() }) it("must return null given null", function() { demand(O.assign(null)).be.null() }) it("must return undefined given undefined and a source", function() { demand(O.assign(undefined, {name: "John"})).be.undefined() }) it("must return null given null and a source", function() { demand(O.assign(null, {name: "John"})).be.null() }) it("must return target given no source", function() { var obj = {} O.assign(obj).must.equal(obj) }) it("must return target given one source", function() { var obj = {} O.assign(obj, {name: "John"}).must.equal(obj) }) it("must assign properties to target from one source", function() { O.assign({}, {name: "John"}).must.eql({name: "John"}) }) it("must assign properties to target from two sources", function() { O.assign({}, {name: "John"}, {age: 13}).must.eql({name: "John", age: 13}) }) it("must overwrite property with later source", function() { O.assign({}, {name: "John"}, {name: "Mike"}).must.eql({name: "Mike"}) }) it("must not change target given no source", function() { O.assign({name: "John"}).must.eql({name: "John"}) }) it("must assign properties from inherited sources", function() { O.assign({}, Object.create({name: "John"})).must.eql({name: "John"}) }) it("must not assign unenumerable properties", function() { var source = Object.defineProperty({}, "name", {value: "John"}) O.assign({}, source).must.eql({}) }) it("must assign properties with undefined value", function() { O.assign({name: "John"}, {name: undefined}).must.eql({name: undefined}) }) }) js-oolong-1.15.1/test/oolong/clone_deep_test.js000066400000000000000000000031341274407531200214620ustar00rootroot00000000000000var O = require("../..") var demand = require("must") describe("Oolong.cloneDeep", function() { it("must return undefined given nothing", function() { demand(O.cloneDeep()).be.undefined() }) it("must return undefined given undefined", function() { demand(O.cloneDeep(undefined)).be.undefined() }) it("must return null given null", function() { demand(O.cloneDeep(null)).be.null() }) it("must return new object", function() { var obj = {} O.cloneDeep(obj).must.not.equal(obj) }) it("must return new object given nested objects", function() { var obj = {attributes: {}} O.cloneDeep(obj).attributes.must.not.equal(obj.attributes) }) it("must clone properties", function() { O.cloneDeep({name: "John", age: 42}).must.eql({name: "John", age: 42}) }) it("must clone nested properties", function() { var obj = {name: "John", attributes: {age: 13}} O.cloneDeep(obj).must.eql({name: "John", attributes: {age: 13}}) }) it("must assign functions", function() { function fn() {} O.cloneDeep({fn: fn}).must.eql({fn: fn}) }) it("must clone properties from inherited sources", function() { O.cloneDeep(Object.create({name: "John"})).must.eql({name: "John"}) }) it("must not clone unenumerable properties", function() { var source = Object.defineProperty({}, "name", {value: "John"}) O.cloneDeep(source).must.eql({}) }) // Just to ensure the target isn't shared between invocations. it("must clone properties when called twice", function() { O.cloneDeep({name: "John"}) O.cloneDeep({age: 42}).must.eql({age: 42}) }) }) js-oolong-1.15.1/test/oolong/clone_test.js000066400000000000000000000026011274407531200204630ustar00rootroot00000000000000var O = require("../..") var demand = require("must") describe("Oolong.clone", function() { it("must return undefined given nothing", function() { demand(O.clone()).be.undefined() }) it("must return undefined given undefined", function() { demand(O.clone(undefined)).be.undefined() }) it("must return null given null", function() { demand(O.clone(null)).be.null() }) it("must return new object", function() { var obj = {} O.clone(obj).must.not.equal(obj) }) it("must clone properties", function() { O.clone({name: "John", age: 42}).must.eql({name: "John", age: 42}) }) it("must assign nested properties", function() { var attrs = {age: 42} var obj = O.clone({name: "John", attrs: attrs}) obj.attrs.must.equal(attrs) }) it("must assign functions", function() { function fn() {} O.clone({fn: fn}).must.eql({fn: fn}) }) it("must clone properties from inherited sources", function() { O.clone(Object.create({name: "John"})).must.eql({name: "John"}) }) it("must not clone unenumerable properties", function() { var source = Object.defineProperty({}, "name", {value: "John"}) O.clone(source).must.eql({}) }) // Just to ensure the target isn't shared between invocations. it("must clone properties when called twice", function() { O.clone({name: "John"}) O.clone({age: 42}).must.eql({age: 42}) }) }) js-oolong-1.15.1/test/oolong/create_test.js000066400000000000000000000020701274407531200206260ustar00rootroot00000000000000var O = require("../..") var demand = require("must") describe("Oolong.create", function() { it("must return an object inheriting from the one given", function() { var prototype = {} var obj = O.create(prototype) Object.getPrototypeOf(obj).must.equal(prototype) }) it("must return an object inheriting from null if given", function() { var obj = O.create(null) demand(Object.getPrototypeOf(obj)).be.null() }) it("must assign properties to target from one source", function() { O.create({}, {name: "John"}).must.eql({name: "John"}) }) it("must assign properties to target from two sources", function() { var obj = O.create({}, {name: "John"}, {age: 13}) obj.must.eql({name: "John", age: 13}) }) it("must throw TypeError given nothing", function() { var err try { O.create() } catch (ex) { err = ex } err.must.be.an.instanceof(TypeError) }) it("must not modify the given prototype", function() { var prototype = {name: ""} O.create(prototype, {name: "John"}) prototype.must.eql({name: ""}) }) }) js-oolong-1.15.1/test/oolong/defaults_test.js000066400000000000000000000044301274407531200211740ustar00rootroot00000000000000var O = require("../..") var demand = require("must") describe("Oolong.defaults", function() { it("must return undefined given nothing", function() { demand(O.defaults()).be.undefined() }) it("must return null given null", function() { demand(O.defaults(null)).be.null() }) it("must return undefined given undefined and a source", function() { demand(O.defaults(undefined, {name: "John"})).be.undefined() }) it("must return null given null and a source", function() { demand(O.defaults(null, {name: "John"})).be.null() }) it("must return target given no source", function() { var obj = {} O.defaults(obj).must.equal(obj) }) it("must return target given one source", function() { var obj = {} O.defaults(obj, {name: "John"}).must.equal(obj) }) it("must assign properties to target from one source", function() { O.defaults({}, {name: "John"}).must.eql({name: "John"}) }) it("must assign properties to target from two sources", function() { O.defaults({}, {name: "John"}, {age: 13}).must.eql({name: "John", age: 13}) }) it("must not assign properties in Object.prototype", function() { O.defaults({}, {hasOwnProperty: true}).must.eql({}) }) it("must assign properties in Object.prototype when inheriting from null", function() { var obj = O.defaults(Object.create(null), {hasOwnProperty: true}) demand(obj).eql({hasOwnProperty: true}) }) it("must not overwrite property if target already has it", function() { O.defaults({name: "John"}, {name: "Mike"}).must.eql({name: "John"}) }) it("must not overwrite property with later source", function() { O.defaults({}, {name: "John"}, {name: "Mike"}).must.eql({name: "John"}) }) it("must not change target given no source", function() { O.defaults({name: "John"}).must.eql({name: "John"}) }) it("must assign properties from inherited sources", function() { O.defaults({}, Object.create({name: "John"})).must.eql({name: "John"}) }) it("must not assign unenumerable properties", function() { var source = Object.defineProperty({}, "name", {value: "John"}) O.defaults({}, source).must.eql({}) }) it("must assign properties with undefined value", function() { O.defaults({}, {name: undefined}).must.eql({name: undefined}) }) }) js-oolong-1.15.1/test/oolong/define_getter_test.js000066400000000000000000000035701274407531200221750ustar00rootroot00000000000000var O = require("../..") describe("Oolong.defineGetter", function() { it("must return object", function() { var obj = {} O.defineGetter(obj, "name", getter).must.equal(obj) }) it("must define a getter", function() { var obj = O.defineGetter({}, "name", getter) var desc = Object.getOwnPropertyDescriptor(obj, "name") desc.get.must.equal(getter) desc.enumerable.must.be.true() desc.configurable.must.be.true() }) it("must not define setter", function() { var obj = O.defineGetter({}, "name", getter) var desc = Object.getOwnPropertyDescriptor(obj, "name") desc.must.have.property("set", undefined) }) it("must not remove setter", function() { var obj = {} O.defineSetter(obj, "name", setter) O.defineGetter(obj, "name", getter) var desc = Object.getOwnPropertyDescriptor(obj, "name") desc.get.must.equal(getter) desc.set.must.equal(setter) }) it("must define property as enumerable if previously so", function() { var obj = Object.defineProperty({}, "name", { writable: true, configurable: true, enumerable: true, value: "John" }) O.defineGetter(obj, "name", getter) var desc = Object.getOwnPropertyDescriptor(obj, "name") desc.get.must.equal(getter) desc.enumerable.must.be.true() desc.configurable.must.be.true() }) // This differs how __defineGetter__ works, but I'd say it's more in line // with how Object.defineProperty behaves. it("must not define property as enumerable if previously not", function() { var obj = Object.defineProperty({}, "name", { writable: true, configurable: true, value: "John" }) O.defineGetter(obj, "name", getter) var desc = Object.getOwnPropertyDescriptor(obj, "name") desc.get.must.equal(getter) desc.enumerable.must.be.false() desc.configurable.must.be.true() }) }) function setter() {} function getter() {} js-oolong-1.15.1/test/oolong/define_setter_test.js000066400000000000000000000035701274407531200222110ustar00rootroot00000000000000var O = require("../..") describe("Oolong.defineSetter", function() { it("must return object", function() { var obj = {} O.defineSetter(obj, "name", setter).must.equal(obj) }) it("must define a setter", function() { var obj = O.defineSetter({}, "name", setter) var desc = Object.getOwnPropertyDescriptor(obj, "name") desc.set.must.equal(setter) desc.enumerable.must.be.true() desc.configurable.must.be.true() }) it("must not define getter", function() { var obj = O.defineSetter({}, "name", setter) var desc = Object.getOwnPropertyDescriptor(obj, "name") desc.must.have.property("get", undefined) }) it("must not remove getter", function() { var obj = {} O.defineGetter(obj, "name", getter) O.defineSetter(obj, "name", setter) var desc = Object.getOwnPropertyDescriptor(obj, "name") desc.get.must.equal(getter) desc.set.must.equal(setter) }) it("must define property as enumerable if previously so", function() { var obj = Object.defineProperty({}, "name", { writable: true, configurable: true, enumerable: true, value: "John" }) O.defineSetter(obj, "name", setter) var desc = Object.getOwnPropertyDescriptor(obj, "name") desc.set.must.equal(setter) desc.enumerable.must.be.true() desc.configurable.must.be.true() }) // This differs how __defineSetter__ works, but I'd say it's more in line // with how Object.defineProperty behaves. it("must not define property as enumerable if previously not", function() { var obj = Object.defineProperty({}, "name", { writable: true, configurable: true, value: "John" }) O.defineSetter(obj, "name", setter) var desc = Object.getOwnPropertyDescriptor(obj, "name") desc.set.must.equal(setter) desc.enumerable.must.be.false() desc.configurable.must.be.true() }) }) function getter() {} function setter() {} js-oolong-1.15.1/test/oolong/each_own_test.js000066400000000000000000000026641274407531200211570ustar00rootroot00000000000000var O = require("../..") var Sinon = require("sinon") describe("Oolong.eachOwn", function() { it("must call function with value, key and object", function() { var obj = {name: "John", age: 42, height: 190} var spy = Sinon.spy() var context = {} O.eachOwn(obj, spy, context) spy.callCount.must.equal(3) spy.args[0][0].must.equal("John") spy.args[0][1].must.equal("name") spy.args[0][2].must.equal(obj) spy.thisValues[0].must.equal(context) spy.args[1][0].must.equal(42) spy.args[1][1].must.equal("age") spy.args[1][2].must.equal(obj) spy.thisValues[1].must.equal(context) spy.args[2][0].must.equal(190) spy.args[2][1].must.equal("height") spy.args[2][2].must.equal(obj) spy.thisValues[2].must.equal(context) }) it("must call function only for own properties", function() { var obj = Object.create({name: "John"}) obj.age = 42 var spy = Sinon.spy() var context = {} O.eachOwn(obj, spy, context) spy.callCount.must.equal(1) spy.args[0][0].must.equal(42) spy.args[0][1].must.equal("age") spy.args[0][2].must.equal(obj) spy.thisValues[0].must.equal(context) }) it("must return the given object", function() { var obj = {} O.eachOwn(obj, noop).must.equal(obj) }) it("must not change the given object", function() { var obj = {name: "John"} O.eachOwn(obj, noop) obj.must.eql({name: "John"}) }) }) function noop() {} js-oolong-1.15.1/test/oolong/each_test.js000066400000000000000000000030771274407531200202730ustar00rootroot00000000000000var O = require("../..") var Sinon = require("sinon") describe("Oolong.each", function() { it("must call function with value, key and object", function() { var obj = {name: "John", age: 42, height: 190} var spy = Sinon.spy() var context = {} O.each(obj, spy, context) spy.callCount.must.equal(3) spy.args[0][0].must.equal("John") spy.args[0][1].must.equal("name") spy.args[0][2].must.equal(obj) spy.thisValues[0].must.equal(context) spy.args[1][0].must.equal(42) spy.args[1][1].must.equal("age") spy.args[1][2].must.equal(obj) spy.thisValues[1].must.equal(context) spy.args[2][0].must.equal(190) spy.args[2][1].must.equal("height") spy.args[2][2].must.equal(obj) spy.thisValues[2].must.equal(context) }) it("must call function for inherited properties", function() { var obj = Object.create({name: "John"}) obj.age = 42 var spy = Sinon.spy() var context = {} O.each(obj, spy, context) spy.callCount.must.equal(2) spy.args[0][0].must.equal(42) spy.args[0][1].must.equal("age") spy.args[0][2].must.equal(obj) spy.thisValues[0].must.equal(context) spy.args[1][0].must.equal("John") spy.args[1][1].must.equal("name") spy.args[1][2].must.equal(obj) spy.thisValues[0].must.equal(context) }) it("must return the given object", function() { var obj = {} O.each(obj, noop).must.equal(obj) }) it("must not change the given object", function() { var obj = {name: "John"} O.each(obj, noop) obj.must.eql({name: "John"}) }) }) function noop() {} js-oolong-1.15.1/test/oolong/filter_test.js000066400000000000000000000017661274407531200206630ustar00rootroot00000000000000var O = require("../..") var Sinon = require("sinon") describe("Oolong.filter", function() { function isEven(value) { return value % 2 == 0 } it("must filter properties", function() { O.filter({a: 1, b: 2, c: 3, d: 4}, isEven).must.eql({b: 2, d: 4}) }) it("must filter inherited properties", function() { var obj = Object.create({a: 1, b: 2, c: 3, d: 4}) O.filter(obj, isEven).must.eql({b: 2, d: 4}) }) it("must call function with value, key and object", function() { var obj = {name: "John"} var spy = Sinon.spy() var context = {} O.filter(obj, spy, context) spy.callCount.must.equal(1) spy.firstCall.args[0].must.equal("John") spy.firstCall.args[1].must.equal("name") spy.firstCall.args[2].must.equal(obj) spy.firstCall.thisValue.must.equal(context) }) it("must not change the given object", function() { var obj = {name: "John"} O.filter(obj, function() { return false }).must.not.equal(obj) obj.must.eql({name: "John"}) }) }) js-oolong-1.15.1/test/oolong/for_each_own_test.js000066400000000000000000000002461274407531200220170ustar00rootroot00000000000000var O = require("../..") describe("Oolong.forEachOwn", function() { it("must be an alias to .eachOwn", function() { O.forEachOwn.must.equal(O.eachOwn) }) }) js-oolong-1.15.1/test/oolong/for_each_test.js000066400000000000000000000002321274407531200211270ustar00rootroot00000000000000var O = require("../..") describe("Oolong.forEach", function() { it("must be an alias to .each", function() { O.forEach.must.equal(O.each) }) }) js-oolong-1.15.1/test/oolong/has_own_test.js000066400000000000000000000011361274407531200210230ustar00rootroot00000000000000var O = require("../..") describe("Oolong.hasOwn", function() { it("must return false given an object without property", function() { O.hasOwn({}, "name").must.be.false() }) it("must return true given an object with property", function() { O.hasOwn({"name": "John"}, "name").must.be.true() }) it("must return true given a property set undefined", function() { O.hasOwn({"name": undefined}, "name").must.be.true() }) it("must return false given an object with an inherited property", function() { O.hasOwn(Object.create({name: "John"}), "name").must.be.false() }) }) js-oolong-1.15.1/test/oolong/has_test.js000066400000000000000000000011151274407531200201350ustar00rootroot00000000000000var O = require("../..") describe("Oolong.has", function() { it("must return false given an object without property", function() { O.has({}, "name").must.be.false() }) it("must return true given an object with property", function() { O.has({"name": "John"}, "name").must.be.true() }) it("must return true given a property set undefined", function() { O.has({"name": undefined}, "name").must.be.true() }) it("must return true given an object with an inherited property", function() { O.has(Object.create({name: "John"}), "name").must.be.true() }) }) js-oolong-1.15.1/test/oolong/is_empty_test.js000066400000000000000000000006651274407531200212240ustar00rootroot00000000000000var O = require("../..") describe("Oolong.isEmpty", function() { it("must return true given an empty object", function() { O.isEmpty({}).must.be.true() }) it("must return false given an non-empty object", function() { O.isEmpty({name: "John"}).must.be.false() }) it("must return false given an object with an inherited property", function() { O.isEmpty(Object.create({name: "John"})).must.be.false() }) }) js-oolong-1.15.1/test/oolong/is_in_own_test.js000066400000000000000000000002361274407531200213510ustar00rootroot00000000000000var O = require("../..") describe("Oolong.isInOwn", function() { it("must be an alias to .hasOwn", function() { O.isInOwn.must.equal(O.hasOwn) }) }) js-oolong-1.15.1/test/oolong/is_in_test.js000066400000000000000000000002221274407531200204610ustar00rootroot00000000000000var O = require("../..") describe("Oolong.isIn", function() { it("must be an alias to .has", function() { O.isIn.must.equal(O.has) }) }) js-oolong-1.15.1/test/oolong/is_object_test.js000066400000000000000000000035161274407531200213320ustar00rootroot00000000000000var O = require("../..") describe("Oolong.isObject", function() { it("must return true given an object literal", function() { O.isObject({}).must.be.true() }) it("must return true given an object inheriting from a literal", function() { O.isObject(Object.create({})).must.be.true() }) it("must return true given Object.prototype", function() { O.isObject(Object.prototype).must.be.true() }) it("must return true given an Object inheritng from null", function() { O.isObject(Object.create(null)).must.be.true() }) it("must return true given Math", function() { O.isObject(Math).must.be.true() }) it("must return true given JSON", function() { O.isObject(JSON).must.be.true() }) // Arguments have all the qualities of an object, so it might as well be one. it("must return true given arguments", function() { O.isObject(arguments).must.be.true() }) it("must return false given undefined", function() { O.isObject(undefined).must.be.false() }) it("must return false given null", function() { O.isObject(null).must.be.false() }) it("must return false given a number", function() { O.isObject(1).must.be.false() }) it("must return false given a string", function() { O.isObject("").must.be.false() }) it("must return true given an array", function() { O.isObject([]).must.be.true() }) it("must return false given a function", function() { O.isObject(noop).must.be.false() }) it("must return true given a regular expression", function() { O.isObject(/./).must.be.true() }) it("must return true given an instance of Date", function() { O.isObject(new Date).must.be.true() }) it("must return true given an instance of a class", function() { function Model() {} O.isObject(new Model).must.be.true() }) }) function noop() {} js-oolong-1.15.1/test/oolong/is_own_empty_test.js000066400000000000000000000011071274407531200220770ustar00rootroot00000000000000var O = require("../..") describe("Oolong.isOwnEmpty", function() { it("must return true given an empty object", function() { O.isOwnEmpty({}).must.be.true() }) it("must return false given an non-empty object", function() { O.isOwnEmpty({name: "John"}).must.be.false() }) it("must return false given an object with hasOwnProperty", function() { O.isOwnEmpty({hasOwnProperty: 42}).must.be.false() }) it("must return true given an object with an inherited property", function() { O.isOwnEmpty(Object.create({name: "John"})).must.be.true() }) }) js-oolong-1.15.1/test/oolong/is_plain_object_test.js000066400000000000000000000043371274407531200225170ustar00rootroot00000000000000var O = require("../..") describe("Oolong.isPlainObject", function() { it("must return true given an object literal", function() { O.isPlainObject({}).must.be.true() }) it("must return true given an object inheriting from a literal", function() { O.isPlainObject(Object.create({})).must.be.true() }) it("must return true given Object.prototype", function() { O.isPlainObject(Object.prototype).must.be.true() }) it("must return true given an Object inheritng from null", function() { O.isPlainObject(Object.create(null)).must.be.true() }) it("must return true given Math", function() { O.isPlainObject(Math).must.be.true() }) it("must return true given JSON", function() { O.isPlainObject(JSON).must.be.true() }) // Arguments have all the qualities of a plain object, so it might as well // be one. it("must return true given arguments", function() { O.isPlainObject(arguments).must.be.true() }) it("must return false given undefined", function() { O.isPlainObject(undefined).must.be.false() }) it("must return false given null", function() { O.isPlainObject(null).must.be.false() }) it("must return false given a number", function() { O.isPlainObject(1).must.be.false() }) it("must return true given a string", function() { O.isPlainObject("").must.be.false() }) it("must return false given an array", function() { O.isPlainObject([]).must.be.false() }) it("must return false given Array.prototype", function() { O.isPlainObject(Array.prototype).must.be.false() }) it("must return false given a function", function() { O.isPlainObject(noop).must.be.false() }) it("must return false given a regular expression", function() { O.isPlainObject(/./).must.be.false() }) it("must return false given an instance of Date", function() { O.isPlainObject(new Date).must.be.false() }) it("must return false given an instance of a class", function() { function Model() {} O.isPlainObject(new Model).must.be.false() }) it("must return false given an object inheriting from an instance", function() { function Model() {} O.isPlainObject(Object.create(new Model)).must.be.false() }) }) function noop() {} js-oolong-1.15.1/test/oolong/keys_test.js000066400000000000000000000005021274407531200203340ustar00rootroot00000000000000var O = require("../..") describe("Oolong.keys", function() { it("must return all enumerable keys of an object", function() { O.keys({a: 1, b: 2}).must.eql(["a", "b"]) }) it("must return inherited enumerable keys of an object", function() { O.keys(Object.create({a: 1, b: 2})).must.eql(["a", "b"]) }) }) js-oolong-1.15.1/test/oolong/lookup_getter_test.js000066400000000000000000000024421274407531200222510ustar00rootroot00000000000000var O = require("../..") var demand = require("must") describe("Oolong.lookupGetter", function() { it("must lookup a getter", function() { var obj = Object.defineProperty({}, "name", {get: getter}) O.lookupGetter(obj, "name").must.equal(getter) }) it("must lookup a getter of an inherited property", function() { var obj = Object.defineProperty({}, "name", {get: getter}) O.lookupGetter(Object.create(obj), "name").must.equal(getter) }) it("must return undefined given no getter", function() { demand(O.lookupGetter({}, "name")).be.undefined() }) it("must not lookup setter", function() { var obj = Object.defineProperty({}, "name", {set: setter}) demand(O.lookupGetter(obj, "name")).be.undefined() }) // NOTE: This test was broken in V8 versions between 3.28.73 (Node v0.12.2) // and 3.28.71.19 (Node v0.12.7). Not sure if it's intentional. // https://code.google.com/p/v8/issues/detail?id=4321 xit("must return undefined given an own property with value", function() { var obj = Object.defineProperty({}, "name", {get: getter}) var child = Object.create(obj, {name: {value: "John", configurable: true}}) child.name.must.equal("John") demand(O.lookupGetter(child, "name")).be.undefined() }) }) function setter() {} function getter() {} js-oolong-1.15.1/test/oolong/lookup_setter_test.js000066400000000000000000000024421274407531200222650ustar00rootroot00000000000000var O = require("../..") var demand = require("must") describe("Oolong.lookupSetter", function() { it("must lookup a setter", function() { var obj = Object.defineProperty({}, "name", {set: setter}) O.lookupSetter(obj, "name").must.equal(setter) }) it("must lookup a setter of an inherited property", function() { var obj = Object.defineProperty({}, "name", {set: setter}) O.lookupSetter(Object.create(obj), "name").must.equal(setter) }) it("must return undefined given no setter", function() { demand(O.lookupSetter({}, "name")).be.undefined() }) it("must not lookup getter", function() { var obj = Object.defineProperty({}, "name", {get: getter}) demand(O.lookupSetter(obj, "name")).be.undefined() }) // NOTE: This test was broken in V8 versions between 3.28.73 (Node v0.12.2) // and 3.28.71.19 (Node v0.12.7). Not sure if it's intentional. // https://code.google.com/p/v8/issues/detail?id=4321 xit("must return undefined given an own property with value", function() { var obj = Object.defineProperty({}, "name", {set: setter}) var child = Object.create(obj, {name: {value: "John", configurable: true}}) child.name.must.equal("John") demand(O.lookupSetter(child, "name")).be.undefined() }) }) function setter() {} function getter() {} js-oolong-1.15.1/test/oolong/map_keys_test.js000066400000000000000000000021031274407531200211700ustar00rootroot00000000000000var O = require("../..") var Sinon = require("sinon") var toUpperCase = Function.call.bind(String.prototype.toUpperCase) describe("Oolong.mapKeys", function() { it("must transform keys", function() { var obj = O.mapKeys({name: "John", age: 32}, toUpperCase) obj.must.eql({NAME: "John", AGE: 32}) }) it("must transform keys of inherited properties", function() { var obj = O.mapKeys(Object.create({name: "John", age: 32}), toUpperCase) obj.must.eql({NAME: "John", AGE: 32}) }) it("must call function with key, value and object", function() { var obj = {name: "John"} var spy = Sinon.spy() var context = {} O.mapKeys(obj, spy, context) spy.callCount.must.equal(1) spy.firstCall.args[0].must.equal("name") spy.firstCall.args[1].must.equal("John") spy.firstCall.args[2].must.equal(obj) spy.firstCall.thisValue.must.equal(context) }) it("must not change the given object", function() { var obj = {name: "John"} O.mapKeys(obj, function() { return "NAME" }).must.not.equal(obj) obj.must.eql({name: "John"}) }) }) js-oolong-1.15.1/test/oolong/map_test.js000066400000000000000000000017031274407531200201420ustar00rootroot00000000000000var O = require("../..") var Sinon = require("sinon") describe("Oolong.map", function() { function double(value) { return value * 2 } it("must map properties", function() { O.map({a: 1, b: 2, c: 3}, double).must.eql({a: 2, b: 4, c: 6}) }) it("must map inherited properties", function() { var obj = Object.create({a: 1, b: 2, c: 3}) O.map(obj, double).must.eql({a: 2, b: 4, c: 6}) }) it("must call function with value, key and object", function() { var obj = {name: "John"} var spy = Sinon.spy() var context = {} O.map(obj, spy, context) spy.callCount.must.equal(1) spy.firstCall.args[0].must.equal("John") spy.firstCall.args[1].must.equal("name") spy.firstCall.args[2].must.equal(obj) spy.firstCall.thisValue.must.equal(context) }) it("must not change the given object", function() { var obj = {answer: 42} O.map(obj, double).must.not.equal(obj) obj.must.eql({answer: 42}) }) }) js-oolong-1.15.1/test/oolong/merge_test.js000066400000000000000000000055241274407531200204710ustar00rootroot00000000000000var O = require("../..") var demand = require("must") describe("Oolong.merge", function() { it("must return undefined given nothing", function() { demand(O.merge()).be.undefined() }) it("must return null given null", function() { demand(O.merge(null)).be.null() }) it("must return undefined given undefined and a source", function() { demand(O.merge(undefined, {name: "John"})).be.undefined() }) it("must return null given null and a source", function() { demand(O.merge(null, {name: "John"})).be.null() }) it("must return target given no source", function() { var obj = {} O.merge(obj).must.equal(obj) }) it("must return target given one source", function() { var obj = {} O.merge(obj, {name: "John"}).must.equal(obj) }) it("must merge 2 plain objects", function() { var target = {name: "John"} O.merge(target, {age: 42}).must.eql({name: "John", age: 42}) }) it("must merge 3 plain objects", function() { var obj = O.merge({name: "John"}, {age: 42}, {height: 190}) obj.must.eql({name: "John", age: 42, height: 190}) }) it("must merge two plain objects deeply", function() { var target = {name: "John", attributes: {age: 13}} var source = {attributes: {height: 190}} var obj = O.merge(target, source) obj.must.eql({name: "John", attributes: {age: 13, height: 190}}) }) it("must replace first object if second not an object", function() { var target = {attributes: {age: 13}} var source = {attributes: null} O.merge(target, source).must.eql({attributes: null}) }) it("must replace second object if first not an object", function() { var target = {attributes: null} var source = {attributes: {age: 13}} O.merge(target, source).must.eql({attributes: {age: 13}}) }) it("must not modify second sources objects", function() { var a = {attributes: {age: 13}} var b = {attributes: {height: 190}} O.merge({}, a, b) a.must.eql({attributes: {age: 13}}) }) it("must not modify deep second sources objects", function() { var a = {john: {attributes: {age: 13}}} var b = {john: {attributes: {height: 190}}} O.merge({}, a, b) a.must.eql({john: {attributes: {age: 13}}}) }) it("must assign non-plain objects directly", function() { var date = new Date var obj = O.merge({name: "John"}, {date: date}) obj.date.must.equal(date) }) it("must merge inherited properties", function() { var obj = O.merge({name: "John"}, Object.create({age: 42})) obj.must.eql({name: "John", age: 42}) }) it("must not assign unenumerable properties", function() { var source = Object.defineProperty({}, "name", {value: "John"}) O.merge({}, source).must.eql({}) }) it("must assign properties with undefined value", function() { O.merge({name: "John"}, {name: undefined}).must.eql({name: undefined}) }) }) js-oolong-1.15.1/test/oolong/object_test.js000066400000000000000000000015711274407531200206360ustar00rootroot00000000000000var O = require("../..") var Sinon = require("sinon") describe("Oolong.object", function() { function lengthOf(value) { return value.length } it("must create object", function() { var obj = O.object(["Alice", "Bob", "Charlie"], lengthOf) obj.must.eql({Alice: 5, Bob: 3, Charlie: 7}) }) it("must call function with value, index and keys", function() { var keys = ["Alice"] var spy = Sinon.spy() var context = {} O.object(keys, spy, context) spy.callCount.must.equal(1) spy.firstCall.args[0].must.equal("Alice") spy.firstCall.args[1].must.equal(0) spy.firstCall.args[2].must.equal(keys) spy.firstCall.thisValue.must.equal(context) }) it("must not change the given object", function() { var obj = ["Alice", "Bob", "Charlie"] O.object(obj, lengthOf).must.not.equal(obj) obj.must.eql(["Alice", "Bob", "Charlie"]) }) }) js-oolong-1.15.1/test/oolong/own_keys_test.js000066400000000000000000000005441274407531200212250ustar00rootroot00000000000000var O = require("../..") describe("Oolong.ownKeys", function() { it("must return all enumerable keys of an object", function() { O.ownKeys({a: 1, b: 2}).must.eql(["a", "b"]) }) it("must not return inherited enumerable keys of an object", function() { var obj = Object.create({a: 1}) obj.b = 2 O.ownKeys(obj).must.eql(["b"]) }) }) js-oolong-1.15.1/test/oolong/pick_deep_test.js000066400000000000000000000052231274407531200213110ustar00rootroot00000000000000var O = require("../..") describe("Oolong.pickDeep", function() { it("must return a new object with given key", function() { var obj = O.pickDeep({name: "Alice", age: 42, height: 100}, "name") obj.must.eql({name: "Alice"}) }) it("must return a new object with given 2nd level key", function() { var person = {name: "Alice", address: {country: "UK", street: "Downing"}} var obj = O.pickDeep(person, "name", ["address", "country"]) obj.must.eql({name: "Alice", address: {country: "UK"}}) }) it("must return a new object with given 3rd level key", function() { var children = {Bob: {name: "Bob", age: "13"}} var person = {name: "Alice", children: children} var obj = O.pickDeep(person, "name", ["children", "Bob", "name"]) obj.must.eql({name: "Alice", children: {Bob: {name: "Bob"}}}) }) it("must return a new object with given keys", function() { var obj = O.pickDeep({name: "Alice", age: 42, height: 100}, "name", "age") obj.must.eql({name: "Alice", age: 42}) }) it("must return a new object with given 2nd level keys", function() { var address = {country: "UK", street: "Downing", apartment: 10} var person = {name: "Alice", address: address} var obj = O.pickDeep(person, "name", ["address", "country"], ["address", "street"]) obj.must.eql({name: "Alice", address: {country: "UK", street: "Downing"}}) }) it("must return an empty object given no keys", function() { O.pickDeep({name: "Alice", age: 42}).must.eql({}) }) it("must return property even if properties inherited", function() { var person = Object.create({name: "Alice", height: 100}) person.age = 42 O.pickDeep(person, "name", "age").must.eql({name: "Alice", age: 42}) }) it("must not change the given object", function() { var obj = {name: "Alice", age: 42} O.pickDeep(obj, "name").must.not.equal(obj) obj.must.eql({name: "Alice", age: 42}) }) it("must not return non-existent keys", function() { var obj = O.pickDeep({name: "Alice", age: 42}, "name", "height") obj.must.eql({name: "Alice"}) }) it("must not return non-existent 2nd level keys", function() { var person = {name: "Alice", address: {country: "UK", street: "Downing"}} var obj = O.pickDeep(person, "name", ["address", "apartment"]) obj.must.eql({name: "Alice"}) }) it("must not return non-existent 3rd level keys", function() { var children = {Bob: {name: "Bob", age: "13"}} var person = {name: "Alice", children: children} var obj = O.pickDeep(person, "name", ["children", "Bob", "height"]) obj.must.eql({name: "Alice"}) }) }) js-oolong-1.15.1/test/oolong/pick_test.js000066400000000000000000000021301274407531200203060ustar00rootroot00000000000000var O = require("../..") describe("Oolong.pick", function() { it("must return a new object with given key", function() { var obj = O.pick({name: "Alice", age: 42, height: 100}, "name") obj.must.eql({name: "Alice"}) }) it("must return a new object with given keys", function() { var obj = O.pick({name: "Alice", age: 42, height: 100}, "name", "age") obj.must.eql({name: "Alice", age: 42}) }) it("must return an empty object given no keys", function() { O.pick({name: "Alice", age: 42}).must.eql({}) }) it("must return property even if properties inherited", function() { var person = Object.create({name: "Alice", height: 100}) person.age = 42 O.pick(person, "name", "age").must.eql({name: "Alice", age: 42}) }) it("must not change the given object", function() { var obj = {name: "Alice", age: 42} O.pick(obj, "name").must.not.equal(obj) obj.must.eql({name: "Alice", age: 42}) }) it("must not return non-existent keys", function() { var obj = O.pick({name: "Alice", age: 42}, "name", "height") obj.must.eql({name: "Alice"}) }) }) js-oolong-1.15.1/test/oolong/pluck_test.js000066400000000000000000000020141274407531200204770ustar00rootroot00000000000000var O = require("../..") describe("Oolong.pluck", function() { it("must return a new object with given property as value", function() { var people = O.pluck({ a: {name: "Alice"}, b: {name: "Bob"}, c: {name: "Charlie"} }, "name") people.must.eql({a: "Alice", b: "Bob", c: "Charlie"}) }) it("must return property even if both object and its child inherited", function() { var people = O.pluck(Object.create({ a: Object.create({name: "Alice"}), b: Object.create({name: "Bob"}), c: Object.create({name: "Charlie"}) }), "name") people.must.eql({a: "Alice", b: "Bob", c: "Charlie"}) }) it("must not change the given object", function() { var obj = {a: "Alice"} O.pluck(obj, "name").must.not.equal(obj) obj.must.eql({a: "Alice"}) }) it("must return undefined for values given a non-existent property", function() { var people = O.pluck({a: {}, b: {}, c: {}}, "name") people.must.eql({a: undefined, b: undefined, c: undefined}) }) }) js-oolong-1.15.1/test/oolong/property_test.js000066400000000000000000000010301274407531200212420ustar00rootroot00000000000000var O = require("../..") var demand = require("must") describe("Oolong.property", function() { it("must return a function that returns the given property", function() { var obj = {name: "John"} O.property("name")(obj).must.equal("John") }) it("must return inherited properties", function() { var obj = Object.create({name: "John"}) O.property("name")(obj).must.equal("John") }) it("must return undefined given a non-existent property", function() { demand(O.property("name")({})).be.undefined() }) }) js-oolong-1.15.1/test/oolong/reject_test.js000066400000000000000000000017651274407531200206510ustar00rootroot00000000000000var O = require("../..") var Sinon = require("sinon") describe("Oolong.reject", function() { function isEven(value) { return value % 2 == 0 } it("must reject properties", function() { O.reject({a: 1, b: 2, c: 3, d: 4}, isEven).must.eql({a: 1, c: 3}) }) it("must reject inherited properties", function() { var obj = Object.create({a: 1, b: 2, c: 3, d: 4}) O.reject(obj, isEven).must.eql({a: 1, c: 3}) }) it("must call function with value, key and object", function() { var obj = {name: "John"} var spy = Sinon.spy() var context = {} O.reject(obj, spy, context) spy.callCount.must.equal(1) spy.firstCall.args[0].must.equal("John") spy.firstCall.args[1].must.equal("name") spy.firstCall.args[2].must.equal(obj) spy.firstCall.thisValue.must.equal(context) }) it("must not change the given object", function() { var obj = {name: "John"} O.reject(obj, function() { return true }).must.not.equal(obj) obj.must.eql({name: "John"}) }) }) js-oolong-1.15.1/test/oolong/set_prototype_of_test.js000066400000000000000000000026201274407531200227700ustar00rootroot00000000000000var O = require("../..") var demand = require("must") describe("Oolong.setPrototypeOf", function() { it("must return object", function() { var obj = {} O.setPrototypeOf(obj, {}).must.equal(obj) }) it("must set object's prototype given object prototype", function() { var obj = {} var prototype = {} O.setPrototypeOf(obj, prototype) Object.getPrototypeOf(obj).must.equal(prototype) }) it("must set object's prototype given null prototype", function() { var obj = {} O.setPrototypeOf(obj, null) demand(Object.getPrototypeOf(obj)).be.null() }) it("must throw given undefined", function() { O.setPrototypeOf.bind(null, undefined, {}).must.throw(TypeError) }) it("must throw given null", function() { O.setPrototypeOf.bind(null, null, {}).must.throw(TypeError) }) it("must ignore if given a number primitive", function() { O.setPrototypeOf(42, {}).must.equal(42) }) it("must throw given a non-extensible object", function() { var obj = Object.preventExtensions({}) O.setPrototypeOf.bind(null, obj, {}).must.throw(TypeError) }) it("must throw given a sealed object", function() { var obj = Object.seal({}) O.setPrototypeOf.bind(null, obj, {}).must.throw(TypeError) }) it("must throw given a frozen object", function() { var obj = Object.freeze({}) O.setPrototypeOf.bind(null, obj, {}).must.throw(TypeError) }) }) js-oolong-1.15.1/test/oolong/values_test.js000066400000000000000000000005041274407531200206620ustar00rootroot00000000000000var O = require("../..") describe("Oolong.values", function() { it("must return all enumerable values of an object", function() { O.values({a: 1, b: 2}).must.eql([1, 2]) }) it("must return inherited enumerable values of an object", function() { O.values(Object.create({a: 1, b: 2})).must.eql([1, 2]) }) }) js-oolong-1.15.1/test/oolong/wrap_test.js000066400000000000000000000005771274407531200203460ustar00rootroot00000000000000var O = require("../..") describe("Oolong.wrap", function() { it("must wrap given value with string", function() { O.wrap(42, "answer").must.eql({answer: 42}) }) if (typeof Symbol != "undefined") it("must wrap given value with symbol ", function() { var symbol = Symbol() var obj = O.wrap(42, symbol) obj.must.eql({}) obj[symbol].must.equal(42) }) })