Index: lib/typedObjects.js
===================================================================
--- a/lib/typedObjects.js
+++ b/lib/typedObjects.js
@@ -150,16 +150,23 @@
  *    get(index): retrieves the array element at specified index.
  *    set(index, value): sets the array element at specified index.
  *    length: number of elements in the array, by default 0. Increase the length
  *        to match your data size.
  *    size: size of the allocated buffer in array elements, will be at least
  *        equal to length. Normally you won't need to set the size explicitly.
  *        However, the size won't decrease automatically if the array gets
  *        smaller so you might want to set it in order to shrink the array.
+ *    splice(), push(), pop(), unshift(), shift(): these work the same as the
+ *        corresponding methods on JavaScript's Array class. Note however that
+ *        using pop() and shift() with arrays of objects is dangerous if you
+ *        want to work with their return value: this operation will call
+ *        release() on the resulting object before returning which might result
+ *        in it being garbage collected. You should call retain() on the array
+ *        element before calling pop() or shift().
  *
  * String type
  * -----------
  *
  * There is a special array type called string:
  *
  *    var str1 = string();            // empty string
  *    var str2 = string(2);           // "\0\0"
Index: lib/typedObjects/arrayTypes.js
===================================================================
--- a/lib/typedObjects/arrayTypes.js
+++ b/lib/typedObjects/arrayTypes.js
@@ -185,16 +185,91 @@ function createSizeWatcher(elementType, 
           removeBuffer(origBufferIndex, buffers, views);
       }
     }
 
     return newSize;
   }
 }
 
+function push()
+{
+  let length = this.length | 0;
+  let newCount = arguments.length | 0;
+  this.length = length + newCount;
+  for (let i = 0; i < newCount; i++)
+    this.set(length + i, arguments[i]);
+  return length + newCount;
+}
+
+function pop()
+{
+  let length = this.length | 0;
+  if (length == 0)
+    throw new Error("No elements in the array");
+
+  let result = this.get(length - 1);
+  this.length = this.length - 1;
+  return result;
+}
+
+function splice(index, count)
+{
+  index = index | 0;
+  count = count | 0;
+  let length = this.length | 0;
+  if (index < 0)
+  {
+    index += length;
+    if (index < 0)
+      index = 0;
+  }
+  if (index > length)
+    index = length;
+  if (index + count > length)
+    count = length - index;
+
+  let newCount = (arguments.length | 0) - 2;
+  let diff = newCount - count;
+  let newLength = length + diff;
+  if (diff > 0)
+  {
+    this.length = newLength;
+    for (let i = length - 1; i >= index + count; i--)
+      this.set(i + diff, this.get(i));
+  }
+  else if (diff < 0)
+  {
+    for (let i = index + count; i < length; i++)
+      this.set(i + diff, this.get(i));
+    this.length = newLength;
+  }
+
+  for (let i = 0; i < newCount; i++)
+    this.set(index + i, arguments[i + 2]);
+}
+
+function unshift(value)
+{
+  let args = [0, 0].concat(Array.prototype.slice.apply(arguments));
+  this.splice.apply(this, args);
+  return this.length | 0;
+}
+
+function shift()
+{
+  let length = this.length | 0;
+  if (length == 0)
+    throw new Error("No elements in the array");
+
+  let result = this.get(0);
+  this.splice(0, 1);
+  return result;
+}
+
 function createArrayType(elementType, typeDescriptor, meta)
 {
   if (typeof meta != "object" || meta == null)
     meta = {};
 
   // We need to make sure that all buffer chunks are big enough to hold a
   // reference in order to manage the free chunks as a linked list. Each array
   // buffer should be dedicated to arrays of particular size - the number of
@@ -237,16 +312,21 @@ function createArrayType(elementType, ty
   typeDescriptor.arrayBufferIndex = int16;
   typeDescriptor.arrayByteOffset = uint32;
   typeDescriptor.getArrayBuffer = function()
   {
     return this.arrayBufferIndex >= 0 ? buffers[this.arrayBufferIndex] : null;
   };
   typeDescriptor.length = uint32;
   typeDescriptor.size = uint32;
+  typeDescriptor.push = push;
+  typeDescriptor.pop = pop;
+  typeDescriptor.splice = splice;
+  typeDescriptor.unshift = unshift;
+  typeDescriptor.shift = shift;
 
   let elementShift = ilog2(elementType.referenceLength | 0);
   typeDescriptor.get = createGetter(elementGetter, elementShift);
   typeDescriptor.set = createSetter(elementSetter, elementShift);
 
   if (meta.hasOwnProperty("constructor") && typeof meta.constructor == "function")
     meta.constructor = createCombinedConstructor(meta.constructor);
   else
Index: test/tests/typedObjects.js
===================================================================
--- a/test/tests/typedObjects.js
+++ b/test/tests/typedObjects.js
@@ -675,16 +675,69 @@
     array5 = uint32Array(9);
     equal(array5.arrayBufferIndex, 5, "Buffer indexes for large arrays aren't reused");
     equal(array5.arrayByteOffset, 0, "Large array is allocated at zero offset");
 
     for (let array of [array1, array2, array3, array4, array5])
       array.release();
   });
 
+  test("Array methods", function()
+  {
+    let {uint32} = require("typedObjects");
+    let uint32Array = uint32.Array({
+      toJS: function()
+      {
+        let result = [];
+        for (let i = 0; i < this.length; i++)
+          result.push(this.get(i));
+        return result;
+      }
+    });
+
+    let array = uint32Array();
+    deepEqual(array.toJS(), [], "Array is initially empty");
+
+    throws(() => array.pop(), "Popping from an empty array throws");
+    throws(() => array.shift(), "Shifting an empty array throws");
+
+    equal(array.push(5), 1, "Pushing returns new length");
+    equal(array.push(2, 8), 3, "Pushing returns new length");
+    deepEqual(array.toJS(), [5, 2, 8], "Pushing three elements succeeded");
+
+    equal(array.pop(), 8, "Popping returns element");
+    equal(array.pop(), 2, "Popping returns element");
+    deepEqual(array.toJS(), [5], "Popping two elements succeeded");
+
+    equal(array.unshift(4), 2, "Unshifting returns new length");
+    equal(array.unshift(0, 9), 4, "Unshifting returns new length");
+    deepEqual(array.toJS(), [0, 9, 4, 5], "Unshifting two elements succeeded");
+
+    equal(array.shift(), 0, "Shifting returns element");
+    equal(array.shift(), 9, "Shifting returns element");
+    deepEqual(array.toJS(), [4, 5], "Shifting by two elements succeeded");
+
+    array.splice(1, 0, 1, 7);
+    deepEqual(array.toJS(), [4, 1, 7, 5], "Using splice to insert elements succeeded");
+    array.splice(2, 1);
+    deepEqual(array.toJS(), [4, 1, 5], "Using splice to remove an element succeeded");
+    array.splice(0, 2, 9);
+    deepEqual(array.toJS(), [9, 5], "Using splice to remove two elements and insert one succeeded");
+    array.splice(1, 1, 4, 2, 7);
+    deepEqual(array.toJS(), [9, 4, 2, 7], "Using splice to remove one element and insert two succeeded");
+    array.splice(3, 8);
+    deepEqual(array.toJS(), [9, 4, 2], "Using splice with excessive count parameter succeeded");
+    array.splice(9, 1, 3);
+    deepEqual(array.toJS(), [9, 4, 2, 3], "Using splice with excessive index parameter succeeded");
+    array.splice(-2, 1, 7);
+    deepEqual(array.toJS(), [9, 4, 7, 3], "Using splice with negative index parameter succeeded");
+    array.splice(-20, 2, 10);
+    deepEqual(array.toJS(), [10, 7, 3], "Using splice with excessive negative index parameter succeeded");
+  });
+
   test("String type", function()
   {
     let {string} = require("typedObjects");
 
     let s1 = string();
     ok(s1, "String created without parameters");
     equal(s1.length, 0, "String length is zero");
     equal(s1.toString(), "", "JavaScript representation is empty string");
