immutable-js
Version:
Immutable types in JavaScript
153 lines (138 loc) • 4.3 kB
JavaScript
/**
* Copyright (c) 2015, Jan Biasi.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import { IndexedCollection } from './Collection';
import { IS_STACK_FLAG, isStack } from './Flags';
import { nullOrUndefined } from './util/is';
import { NativeObject, NativeArray, isNative } from './Native';
import { OwnerID } from './Owner';
import { typedef as defineTypeOf } from './util/toolset';
export var STACK_TYPEDEF = '[IndexedCollection Stack]';
export class Stack extends IndexedCollection {
constructor() {
var args = Array.prototype.slice.call(arguments);
if(nullOrUndefined(args)) {
return emptyStack();
} else if(args.length === 1) {
let singleArg = args[0];
if(Array.isArray(singleArg)) {
return makeStack(singleArg);
} else if(typeof singleArg === 'object') {
return makeStack(objectToArray(singleArg));
}
} else if(args.length > 1) {
return makeStack(args);
}
}
static of(...values) {
return new Stack(values);
}
push(...values) {
if(this.__ownerID) {
values.forEach(v => this.__internal.push(v));
this.size = this.__internal.length;
this.__altered = true;
return this;
}
return new Stack(
this.__internal.__clone().concat(
Array.prototype.slice.call(arguments)
)
);
}
shift() {
if(this.__ownerID) {
this.__internal.pop();
this.size = this.__internal.length;
this.__altered = true;
return this;
}
var cloned = this.__internal.__clone();
var newSize = cloned.pop();
return new Stack(cloned);
}
clear() {
if(this.size === 0) {
return this;
}
if(this.__ownerID) {
this.size = 0;
this.__altered = true;
return this.toStack();
}
return emptyStack();
}
toString() {
return this.__toString('Stack [', this.__internal.join(',') ,']');
}
toStack() {
return this;
}
__ensureOwner(ownerID) {
if(ownerID === this.__ownerID) {
return this;
}
if(!ownerID || nullOrUndefined(ownerID)) {
this.__ownerID = ownerID;
this.__altered = false;
return this;
}
return makeStack(this.__internal, ownerID);
}
__iterate(handle, reverse) {
var maxLength = this.size;
for(var n = 0; n <= maxLength; n++) {
let entry = this.__internal[reverse ? maxLength - n : n];
if(handle(entry, n, this) === false) {
return n + 1;
}
}
return n;
}
}
defineTypeOf(Stack, STACK_TYPEDEF);
Stack.prototype[IS_STACK_FLAG] = true;
var EMPTY_STACK;
function emptyStack() {
return EMPTY_STACK || (EMPTY_STACK = makeStack());
}
function makeStack(array, ownerID) {
var stack = Object.create(Stack.prototype);
stack.__ownerID = ownerID;
stack.__altered = false;
if(isNative(array)) {
stack.__internal = array.toNative();
} else {
stack.__internal = new NativeArray();
if(Array.isArray(array)) {
array.forEach(v => stack.__internal.push(v));
stack.size = array.length;
}
}
return stack;
}
function objectToArray(object) {
var stack = new NativeArray();
if(object && typeof object === 'object') {
for(var key in object) {
if(object[key] && object.hasOwnProperty(key)) {
if(typeof object[key] === 'object') {
stack.push(objectToArray(object[key]));
} else if(!nullOrUndefined(object[key])) {
stack.push(object[key]);
}
}
}
} else {
throw TypeError(
'Object to array conversion needs object ' +
'and not ' + typeof object
);
}
return stack;
}