You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by do...@apache.org on 2008/01/10 02:18:20 UTC

svn commit: r610628 [1/2] - in /incubator/shindig/trunk: features/caja/ features/opensocial-reference/ features/opensocial-samplecontainer/ javascript/opensocial/

Author: doll
Date: Wed Jan  9 17:17:56 2008
New Revision: 610628

URL: http://svn.apache.org/viewvc?rev=610628&view=rev
Log:
- Moved the opensocial reference code into the new features directory. 
- Added the samplecontainer.js file which can now be accessed by require feature="opensocial-samplecontainer". This has a small amount of hardcoded mock data, hopefully this will change to use state files like the code.google.com site in the next change. 
- Added a caja feature. Unfortunately I had to copy the caja.js file from their code.google.com site. Hopefully we will be able to pull this from maven at a later date. 

The addition of these features means shindig can parse/run cajoled opensocial gadgets. 

Next steps are to clean the caja related code in container.js (very hacky right now) and to add a sample container environment for testing gadgets. 



Added:
    incubator/shindig/trunk/features/caja/
    incubator/shindig/trunk/features/caja/caja.js   (with props)
    incubator/shindig/trunk/features/caja/feature.xml
    incubator/shindig/trunk/features/opensocial-reference/
    incubator/shindig/trunk/features/opensocial-reference/activity.js   (with props)
    incubator/shindig/trunk/features/opensocial-reference/collection.js   (with props)
    incubator/shindig/trunk/features/opensocial-reference/container.js   (with props)
    incubator/shindig/trunk/features/opensocial-reference/datarequest.js   (with props)
    incubator/shindig/trunk/features/opensocial-reference/dataresponse.js   (with props)
    incubator/shindig/trunk/features/opensocial-reference/environment.js   (with props)
    incubator/shindig/trunk/features/opensocial-reference/feature.xml
    incubator/shindig/trunk/features/opensocial-reference/opensocial.js   (with props)
    incubator/shindig/trunk/features/opensocial-reference/person.js   (with props)
    incubator/shindig/trunk/features/opensocial-reference/responseitem.js   (with props)
    incubator/shindig/trunk/features/opensocial-reference/surface.js   (with props)
    incubator/shindig/trunk/features/opensocial-samplecontainer/
    incubator/shindig/trunk/features/opensocial-samplecontainer/feature.xml
    incubator/shindig/trunk/features/opensocial-samplecontainer/samplecontainer.js
Removed:
    incubator/shindig/trunk/javascript/opensocial/

Added: incubator/shindig/trunk/features/caja/caja.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/caja/caja.js?rev=610628&view=auto
==============================================================================
--- incubator/shindig/trunk/features/caja/caja.js (added)
+++ incubator/shindig/trunk/features/caja/caja.js Wed Jan  9 17:17:56 2008
@@ -0,0 +1,1787 @@
+// Copyright (C) 2007 Google Inc.
+//      
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// .............................................................................
+
+// This module is the Caja runtime library. It is written in
+// Javascript, not Caja, and would be rejected by the Caja
+// translator. This module exports two globals: 
+// * "___" for use by the output of the Caja translator and by some
+//   other untranslated Javascript code.
+// * "caja" providing some common services to the Caja programmer.
+
+// TODO(erights): All code text in comments should be enclosed in
+// <tt>code</tt>.
+
+
+////////////////////////////////////////////////////////////////////////
+// Caja adds the following common Javascript extensions to ES3
+// TODO(erights): Move such extensions to a separate extensions.js,
+//                and change the conflict rule (for now) to fail on
+//                detecting a conflict.
+////////////////////////////////////////////////////////////////////////
+
+if (Array.prototype.indexOf === undefined) {
+  /** 
+   * Returns the first index at which the specimen is found (by
+   * "===") or -1 if none.  
+   */
+  Array.prototype.indexOf = function(specimen) {
+    var len = this.length;
+    for (var i = 0; i < len; i += 1) {
+      if (this[i] === specimen) {
+        return i;
+      }
+    }
+    return -1;
+  };
+}
+
+if (Array.prototype.lastIndexOf === undefined) {
+  /** 
+   * Returns the last index at which the specimen is found (by
+   * "===") or -1 if none.  
+   */
+  Array.prototype.lastIndexOf = function(specimen) {
+    for (var i = this.length; --i >= 0; ) {
+      if (this[i] === specimen) {
+        return i;
+      }
+    }
+    return -1;
+  };
+}
+
+if (Date.prototype.toISOString === undefined) {
+  /**
+   * Like the date.toJSONString() method defined in json.js, but
+   * without the surrounding quotes.
+   */
+  Date.prototype.toISOString = function() {
+    function f(n) {
+      return n < 10 ? '0' + n : n;
+    }
+    return (this.getUTCFullYear()     + '-' +
+            f(this.getUTCMonth() + 1) + '-' +
+            f(this.getUTCDate())      + 'T' +
+            f(this.getUTCHours())     + ':' +
+            f(this.getUTCMinutes())   + ':' +
+            f(this.getUTCSeconds())   + 'Z');
+  };
+}
+
+
+// caja.js exports the following names to the Javascript global
+// namespace. Caja code can only use the "caja" object. The "___"
+// object is for use by code generated by the Caja translator, and by
+// Javascript code (such as a powerbox) in the embedding application.
+
+// Caja virtually adds Object.prototype.freeze_(), so that a
+// constructed object can freeze itself, but its clients cannot freeze
+// it. However, in order not to disrupt innocent code (see
+// canInnocentEnum() below), the only property names Caja may add to
+// primordial objects are names ending in triple underbar. Therefore,
+// Caja instead adds Object.prototype.freeze__handler___().
+
+var caja;
+var ___;
+
+// Explicitly passing in the actual global object to avoid
+// ReferenceErrors when referring to potentially nonexistent objects
+// like HTMLDivElement.
+
+(function(global) {
+  
+  ////////////////////////////////////////////////////////////////////////
+  // Diagnostics and condition enforcement
+  ////////////////////////////////////////////////////////////////////////
+  
+  /**
+   * The initial default ___.log(str) does nothing. 
+   * <p>
+   * Note: JavaScript has no macros, so even in the "does nothing"
+   * case, remember that the arguments are still evaluated. 
+   */
+  var myLogFunc_ = function(str) {};
+
+  /**
+   * Gets the currently registered ___.log(str) function.
+   */
+  function getLogFunc() { return myLogFunc_; }
+
+  /**
+   * Register newLogFunc to be called by ___.log(str)
+   */
+  function setLogFunc(newLogFunc) { myLogFunc_ = newLogFunc; }
+
+  /**
+   * Calls the currently registered logging function.
+   */
+  function log(str) { myLogFunc_(String(str)); }
+
+
+  /** 
+   * Throw, and optionally log, an error whose message is the
+   * concatentation of the arguments.
+   * <p>
+   * The arguments are converted to strings (presumably by an
+   * implicit call to ".toString()") and appended together to make
+   * the message of the Error that's thrown.
+   */
+  function fail(var_args) {
+    var message = Array.prototype.slice.call(arguments, 0).join('');
+    log(message);
+    throw new Error(message);
+  }
+  
+  /** 
+   * Like an assert that can't be turned off.
+   * <p>
+   * Either returns true (on success) or throws (on failure). The
+   * arguments starting with <tt>var_args</tt> are converted to
+   * strings and appended together to make the message of the Error
+   * that's thrown.
+   * <p>
+   * TODO(erights) We may deprecate this in favor of <pre>
+   *     test || fail(var_args...)
+   * </pre> or <pre>
+   *     if (!test) { fail(var_args...); }
+   * </pre>
+   */
+  function enforce(test, var_args) {
+    return test || fail.apply({}, 
+                              Array.prototype.slice.call(arguments, 1));
+  }
+  
+  /**
+   * Enforces <tt>typeof specimen === typename</tt>, in which case
+   * specimen is returned.
+   * <p>
+   * If not, throws an informative TypeError
+   * <p>
+   * opt_name, if provided, should be a name or description of the
+   * specimen used only to generate friendlier error messages.
+   */
+  function enforceType(specimen, typename, opt_name) {
+    if (typeof specimen !== typename) {
+      fail('expected ', typename, ' instead of ', typeof specimen,
+           ': ', (opt_name || specimen));
+    }
+    return specimen;
+  }
+  
+  /**
+   * Enforces that specimen is a non-negative integer within the range
+   * of exactly representable consecutive integers, in which case
+   * specimen is returned.
+   * <p>
+   * "Nat" is short for "Natural number".
+   */
+  function enforceNat(specimen) {
+    enforceType(specimen, 'number');
+    if (Math.floor(specimen) !== specimen) {
+      fail('Must be integral: ', specimen);
+    }
+    if (specimen < 0) {
+      fail('Must not be negative: ', specimen);
+    }
+    // Could pre-compute precision limit, but probably not faster
+    // enough to be worth it.
+    if (Math.floor(specimen-1) !== specimen-1) {
+      fail('Beyond precision limit: ', specimen);
+    }
+    if (Math.floor(specimen-1) >= specimen) {
+      fail('Must not be infinite: ', specimen);
+    }
+    return specimen;
+  }
+  
+  ////////////////////////////////////////////////////////////////////////
+  // Privileged fault handlers
+  ////////////////////////////////////////////////////////////////////////
+  
+  /**
+   * 
+   */
+  var myKeeper_ = {
+
+    /**
+     *
+     */
+    toString: function() { return '<Logging Keeper>'; },
+
+    /**
+     * 
+     */
+    handleRead: function(obj, name) {
+      log('Not readable: (' + obj + ').' + name);
+      return undefined; 
+    },
+
+    /**
+     * 
+     */
+    handleCall: function(obj, name, args) {
+      fail('Not callable: (', obj, ').', name);
+    },
+
+    /**
+     * 
+     */
+    handleSet: function(obj, name, val) {
+      fail('Not settable: (', obj, ').', name);
+    },
+
+    /**
+     * 
+     */
+    handleDelete: function(obj, name) {
+      fail('Not deletable: (', obj, ').', name);
+    }
+  };
+
+  /**
+   * 
+   */
+  function getKeeper() { return myKeeper_; }
+
+  /**
+   * 
+   */
+  function setKeeper(newKeeper) { myKeeper_ = newKeeper; }
+
+  /**
+   * 
+   */
+  Object.prototype.handleRead___ = function(name) {
+    var handlerName = name + '_getter___';
+    if (this[handlerName]) {
+      return this[handlerName]();
+    }
+    return myKeeper_.handleRead(this, name);
+  };
+
+  /**
+   * 
+   */
+  Object.prototype.handleCall___ = function(name, args) {
+    var handlerName = name + '_handler___';
+    if (this[handlerName]) {
+      return this[handlerName].call(this, args);
+    }
+    return myKeeper_.handleCall(this, name, args);
+  };
+
+  /**
+   * 
+   */
+  Object.prototype.handleSet___ = function(name, val) {
+    var handlerName = name + '_setter___';
+    if (this[handlerName]) {
+      return this[handlerName](val);
+    }
+    return myKeeper_.handleSet(this, name, val);
+  };
+
+  /**
+   * 
+   */
+  Object.prototype.handleDelete___ = function(name) {
+    var handlerName = name + '_deleter___';
+    if (this[handlerName]) {
+      return this[handlerName]();
+    }
+    return myKeeper_.handleDelete(this, name);
+  };
+  
+  ////////////////////////////////////////////////////////////////////////
+  // Overriding some very basic primordial methods
+  ////////////////////////////////////////////////////////////////////////
+  
+  /**
+   * Returns true only if we can call
+   * Object.prototype.hasOwnProperty on this object without
+   * exploding. 
+   * <p>
+   * On Firefox, it seems that calling hasOwnProperty on an
+   * HTMLDivElement sometimes causes an
+   * "Illegal operation on WrappedNative prototype object".
+   * <p>
+   * SECURITY BUG STOPGAP TODO(erights)
+   */
+  var canCallHasOwnProperty = function(obj) { return true; };
+  
+  // When we're in a non-browser environment, such that there isn't
+  // a global HTMLDivElement, then we don't need to worry about
+  // this bug.
+  if (typeof global.HTMLDivElement === 'function') {
+    canCallHasOwnProperty = function(obj) {
+      return !(obj instanceof global.HTMLDivElement);
+    };
+  }
+  
+  var originalHOP_ = Object.prototype.hasOwnProperty;
+  
+  /**
+   * <tt>hasOwnProp(obj.prop)</tt> means what
+   * <tt>obj.hasOwnProperty(prop)</tt> would normally mean in an
+   * unmodified Javascript system.
+   */
+  function hasOwnProp(obj, name) { 
+    var t = typeof obj;
+    if (t !== 'object' && t !== 'function') { 
+      return false; 
+    }
+    if (canCallHasOwnProperty(obj)) {
+      // Fails in Firefox for some DOM objects intermittently(?!) 
+      // with "Illegal operation on WrappedNative prototype object".
+      // For these, canCallHasOwnProperty must say false.
+      return originalHOP_.call(obj, name); 
+    } else {
+      return false;
+    }
+  }
+  
+  ////////////////////////////////////////////////////////////////////////
+  // walking prototype chain, checking JSON containers
+  ////////////////////////////////////////////////////////////////////////
+  
+  /**
+   * Does str end with suffix? 
+   */
+  function endsWith(str, suffix) {
+    enforceType(str, 'string');
+    enforceType(suffix, 'string');
+    var strLen = str.length;
+    var sufLen = suffix.length;
+    return strLen >= sufLen && 
+      (str.substring(strLen-sufLen, strLen) === suffix);
+  }
+  
+  /**
+   * Returns the 'constructor' property of obj's prototype.
+   * <p>
+   * By "obj's prototype", we mean the object that obj directly
+   * inherits from, not the value of its 'prototype' property. If
+   * obj has a '__proto__' property, then we assume we're on a
+   * platform (like Firefox) in which this reliably gives us obj's
+   * prototype. Otherwise, we memoize the apparent prototype into
+   * '__proto__' to speed up future queries.
+   * <p>
+   * If obj is a function or not an object, return undefined.
+   */
+  function directConstructor(obj) {
+    if (obj === null) { return undefined; }
+    if (typeof obj !== 'object') {
+      // Note that functions thereby return undefined,
+      // so directConstructor() doesn't provide access to the
+      // forbidden Function constructor.
+      return undefined;
+    }
+    // The following test will initially return false in IE
+    if (hasOwnProp(obj, '__proto__')) { 
+      if (obj.__proto__ === null) { return undefined; }
+      return obj.__proto__.constructor; 
+    }
+    var result;
+    if (!hasOwnProp(obj, 'constructor')) { 
+      result = obj.constructor;
+    } else {
+      var oldConstr = obj.constructor;
+      if (!(delete obj.constructor)) { return undefined; }
+      result = obj.constructor;
+      obj.constructor = oldConstr;
+    }
+    if (result.prototype.constructor === result) {
+      // Memoize, so it'll be faster next time.
+      obj.__proto__ = result.prototype;
+    }
+    return result;
+  }
+  
+  /**
+   * A JSON container is an object whose direct constructor is
+   * Object or Array.
+   * <p>
+   * These are the kinds of non-primitive objects that can be
+   * expressed in the JSON language.
+   */
+  function isJSONContainer(obj) {
+    var constr = directConstructor(obj);
+    return constr === Object || constr === Array;
+  }
+  
+  /**
+   * If obj is frozen, Caja code cannot directly assign to
+   * properties of obj, nor directly add or delete properties to
+   * obj.
+   * <p>
+   * The status of being frozen is not inherited. If A inherits from
+   * B (i.e., if A's prototype is B), then (we hope) B must be
+   * frozen regardless, but A may or may not be frozen.
+   * <p>
+   * If typeof <tt>obj</tt> is neither 'object' nor 'function', then
+   * it's currently considered frozen.
+   */
+  function isFrozen(obj) { 
+    var t = typeof obj;
+    if (t !== 'object' && t !== 'function') { 
+      return true; 
+    }
+    return hasOwnProp(obj, '___FROZEN___'); 
+  }
+  
+  /**
+   * Mark obj as frozen so that Caja code cannot directly assign to its
+   * properties.
+   * <p>
+   * If obj is a function, also freeze obj.prototype.
+   * <p>
+   * This appears as <tt>___.primFreeze(obj)</tt> and is wrapped by
+   * the virtual <tt>Object.prototype.freeze_()</tt>.
+   */
+  function primFreeze(obj) {
+    if (null === obj) { return obj; }
+    if (isFrozen(obj)) { return obj; }
+    var typ = typeof obj;
+    if (typ !== 'object' && typ !== 'function') { return obj; }
+
+    // badFlags are names of properties we need to turn off.
+    // We accumulate these first, so that we're not in the midst of a
+    // for/in loop on obj while we're deleting properties from obj.
+    var badFlags = []; 
+    for (var k in obj) {
+      if (endsWith(k, '_canSet___') || endsWith(k, '_canDelete___')) { 
+        if (obj[k]) {
+          badFlags.push(k);
+        }
+      }
+    }
+    for (var i = 0; i < badFlags.length; i++) {
+      var flag = badFlags[i];
+      if (hasOwnProp(obj, flag)) {
+        if (!(delete obj[flag])) {
+          fail('internal: failed delete: ', obj, '.', flag);
+        }
+      }
+      if (obj[flag]) {
+        // At the time of this writing, this case
+        // should never be able to happen, since
+        // prototypes are always frozen before use,
+        // and frozen objects cannot have these flags
+        // set on them. We code it this way to allow
+        // for a future optimization, where the
+        // prototype can record as canSet those
+        // properties that appear in instances that
+        // inherit from this prototype. 
+        obj[flag] = false;
+      }
+    }
+    obj.___FROZEN___ = true;
+    if (typ === 'function') {
+      // Do last to avoid possible infinite recursion.
+      primFreeze(obj.prototype);
+    }
+    return obj;
+  }
+  
+  /**
+   * Like primFreeze(obj), but applicable only to JSON containers.
+   */
+  function freeze(obj) {
+    if (!isJSONContainer(obj)) {
+      fail('caja.freeze(obj) applies only to JSON Containers: ', obj);
+    }
+    return primFreeze(obj);
+  }
+  
+  /**
+   * Makes a mutable copy of a JSON container.
+   * <p>
+   * Even if the original is frozen, the copy will still be mutable.
+   */
+  function copy(obj) {
+    if (!isJSONContainer(obj)) {
+      fail('caja.copy(obj) applies only to JSON Containers: ', obj);
+    }
+    var result = (obj instanceof Array) ? [] : {};
+    each(obj, simpleFunc(function(k, v) {
+      result[k] = v;
+    }));
+    return result;
+  }
+  
+  /**
+   * A snapshot of a JSON container is a frozen copy of that
+   * container. 
+   */
+  function snapshot(obj) {
+    return primFreeze(copy(obj));
+  }
+  
+  ////////////////////////////////////////////////////////////////////////
+  // Accessing property attributes
+  ////////////////////////////////////////////////////////////////////////
+  
+  /** Tests whether the fast-path canRead flag is set. */
+  function canRead(obj, name)   { return !!obj[name + '_canRead___']; }
+  /** Tests whether the fast-path canEnum flag is set. */
+  function canEnum(obj, name)   { return !!obj[name + '_canEnum___']; }
+  /** Tests whether the fast-path canCall flag is set. */
+  function canCall(obj, name)   { return !!obj[name + '_canCall___']; }
+  /** Tests whether the fast-path canSet flag is set. */
+  function canSet(obj, name)    { return !!obj[name + '_canSet___']; }
+  /** Tests whether the fast-path canDelete flag is set. */
+  function canDelete(obj, name) { return !!obj[name + '_canDelete___']; }
+  
+  /** 
+   * Sets the fast-path canRead flag.
+   * <p>
+   * The various <tt>allow*</tt> functions are called externally by
+   * Javascript code to express whitelisting taming decisions. And
+   * they are called internally to memoize decisions arrived at by
+   * other means. 
+   */
+  function allowRead(obj, name) { 
+    obj[name + '_canRead___'] = true; 
+  }
+  
+  /** allowEnum implies allowRead */
+  function allowEnum(obj, name) { 
+    allowRead(obj, name);
+    obj[name + '_canEnum___'] = true;
+  }
+  
+  /** 
+   * Simple functions should callable and readable, but methods
+   * should only be callable.
+   */
+  function allowCall(obj, name) { 
+    obj[name + '_canCall___'] = true; 
+  }
+  
+  /**
+   * allowSet implies allowEnum and allowRead.
+   */
+  function allowSet(obj, name) {
+    if (isFrozen(obj)) {
+      fail("Can't set .", name, ' on frozen (', obj, ')');
+    }
+    allowEnum(obj, name);
+    obj[name + '_canSet___'] = true;
+  }
+  
+  /**
+   * BUG TODO(erights): allowDelete is not yet specified or
+   * implemented. 
+   */
+  function allowDelete(obj, name) {
+    if (isFrozen(obj)) {
+      fail("Can't delete .", name, ' on frozen (', obj, ')');
+    }
+    fail('TODO(erights): allowDelete() not yet implemented');
+    obj[name + '_canDelete___'] = true;
+  }
+  
+  ////////////////////////////////////////////////////////////////////////
+  // Classifying functions
+  ////////////////////////////////////////////////////////////////////////
+  
+  function isCtor(constr)    { return !!constr.___CONSTRUCTOR___; }
+  function isMethod(meth)    { return '___METHOD_OF___' in meth; }
+  function isSimpleFunc(fun) { return !!fun.___SIMPLE_FUNC___; }
+  
+  /** 
+   * Mark constr as a constructor.
+   * <p>
+   * If opt_Sup is provided, set constr.Super = opt_Sup.
+   * <p>
+   * A function is tamed and classified by calling one of ctor(),
+   * method(), or simpleFunc(). Each of these checks that the
+   * function hasn't already been classified by any of the others. A
+   * function which has not been so classified is an <i>untamed
+   * function</i>. 
+   * <p>
+   * opt_name, if provided, should be the name of the constructor
+   * function. Currently, this is used only to generate friendlier
+   * error messages.
+   */
+  function ctor(constr, opt_Sup, opt_name) {
+    enforceType(constr, 'function', opt_name);
+    if (isMethod(constr)) {
+      fail("Methods can't be constructors: ", constr);
+    }
+    if (isSimpleFunc(constr)) {
+      fail("Simple functions can't be constructors: ", constr);
+    }
+    constr.___CONSTRUCTOR___ = true;
+    if (opt_Sup) {
+      opt_Sup = asCtor(opt_Sup);
+      if (hasOwnProp(constr, 'Super')) {
+        if (constr.Super !== opt_Sup) {
+          fail("Can't inherit twice: ", constr, ',', opt_Sup);
+        }
+      } else {
+        if (isFrozen(constr)) {
+          fail('Derived constructor already frozen: ', constr);
+        }
+        constr.Super = opt_Sup;
+      }
+    }
+    return constr;  // translator freezes constructor later
+  }
+  
+  /** 
+   * Mark meth as a method of instances of constr. 
+   * <p>
+   * opt_name, if provided, should be the message name associated
+   * with the method. Currently, this is used only to generate
+   * friendlier error messages.
+   */
+  function method(constr, meth, opt_name) {
+    enforceType(meth, 'function', opt_name);
+    if (isCtor(meth)) {
+      fail("constructors can't be methods: ", meth);
+    }
+    if (isSimpleFunc(constr)) {
+      fail("Simple functions can't be methods: ", meth);
+    }
+    meth.___METHOD_OF___ = asCtorOnly(constr);
+    return primFreeze(meth);
+  }
+  
+  /** 
+   * Mark fun as a simple function.
+   * <p>
+   * opt_name, if provided, should be the name of the 
+   * function. Currently, this is used only to generate friendlier
+   * error messages.
+   */
+  function simpleFunc(fun, opt_name) {
+    enforceType(fun, 'function', opt_name);
+    if (isCtor(fun)) {
+      fail("Constructors can't be simple functions: ", fun);
+    }
+    if (isMethod(fun)) {
+      fail("Methods can't be simple function: ", fun);
+    }
+    fun.___SIMPLE_FUNC___ = true;
+    fun.apply_canCall___ = true;
+    fun.call_canCall___ = true;
+    return fun;  // translator freezes fun later
+  }
+  
+  /** This "Only" form doesn't freeze */
+  function asCtorOnly(constr) {
+    if (isCtor(constr) || isSimpleFunc(constr)) { 
+      return constr; 
+    }
+    
+    enforceType(constr, 'function');
+    if (isMethod(constr)) {
+      fail("Methods can't be called as constructors: ", constr);
+    }
+    fail("Untamed functions can't be called as constructors: ", constr);
+  }
+  
+  /** Only constructors and simple functions can be called as constructors */
+  function asCtor(constr) {
+    return primFreeze(asCtorOnly(constr)); 
+  }
+  
+  /** Only methods and simple functions can be called as methods */
+  function asMethod(meth) {
+    if (isSimpleFunc(meth) || isMethod(meth)) { 
+      if (!isFrozen(meth)) {
+        fail('internal: non-frozen func stored as method: ', meth);
+      }
+      return meth; 
+    }
+    
+    enforceType(meth, 'function');
+    if (isCtor(meth)) {
+      fail("Constructors can't be called as methods: ", meth);
+    }
+    fail("Untamed functions can't be called as methods: ", meth);
+  }
+  
+  /** Only simple functions can be called as simple functions */
+  function asSimpleFunc(fun) {
+    if (isSimpleFunc(fun)) { 
+      return primFreeze(fun); 
+    }
+    
+    enforceType(fun, 'function');
+    if (isCtor(fun)) {
+      fail("Constructors can't be called as simple functions: ", fun);
+    }
+    if (isMethod(fun)) {
+      fail("Methods can't be called as simple functions: ", fun);
+    }
+    fail("Untamed functions can't be called as simple functions: ", fun);
+  }
+  
+  /** 
+   * Sets constr.prototype[name] = member.
+   * <p>
+   * If member is a method of constr, make it callable.
+   * If member is a simple function, make it callable and readable.
+   * Else make it readable.
+   */
+  function setMember(constr, name, member) {
+    name = String(name);
+    if (endsWith(name, '__')) {
+      fail('Reserved name: ', name);
+    }
+    var proto = readPub(asCtorOnly(constr), 'prototype');
+    // We allow prototype members to end in a single "_".
+    if (!canSetProp(proto, name)) {
+      fail('not settable: ', name);
+    }
+    if (member.___METHOD_OF___ === constr) {
+      allowCall(proto, name);  // grant
+    } else if (isSimpleFunc(member)) {
+      allowCall(proto, name);  // grant
+      allowSet(proto, name);  // grant
+    } else {
+      allowSet(proto, name);  // grant
+    }
+    proto[name] = member;
+  }
+  
+  ////////////////////////////////////////////////////////////////////////
+  // Accessing properties
+  ////////////////////////////////////////////////////////////////////////
+  
+  /** 
+   * Can a constructed Caja object read this property on itself? 
+   * <p>
+   * Can a Caja method whose <tt>this</tt> is bound to <tt>that</tt>
+   * read its own <tt>name</tt> property? For properties added to
+   * the object by Caja code, the answer is yes. For other
+   * properties, which must therefore be inherited from a prototype
+   * written in Javascript rather than Caja, the answer is: iff they
+   * were whitelisted.
+   */
+  function canReadProp(that, name) {
+    name = String(name);
+    if (endsWith(name, '__')) { return false; }
+    return canRead(that, name);
+  }
+  
+  /** 
+   * A constructed Caja object's attempt to read this property on
+   * itself.
+   * <p>
+   * If it can't,  it reads <tt>undefined</tt> instead.
+   */
+  function readProp(that, name) {
+    name = String(name);
+    return canReadProp(that, name) ? that[name] : that.handleRead___(name);
+  }
+  
+  /** 
+   * Can a Caja client of <tt>obj</tt> read its <name> property? 
+   * <p>
+   * If the property is Internal (i.e. ends in an '_'), then no.
+   * If the property was defined by Caja code, then yes. If it was
+   * whitelisted, then yes. Or if the property is an own property of
+   * a JSON container, then yes.
+   */
+  function canReadPub(obj, name) {
+    name = String(name);
+    if (endsWith(name, '_')) { return false; }
+    if (canRead(obj, name)) { return true; }
+    if (!isJSONContainer(obj)) { return false; }
+    if (!hasOwnProp(obj, name)) { return false; }
+    allowRead(obj, name);  // memoize
+    return true;
+  }
+  
+  /**
+   * Caja code attempting to read a property on something besides
+   * <tt>this</tt>.
+   * <p>
+   * If it can't, it reads <tt>undefined</tt> instead.
+   */
+  function readPub(obj, name) {
+    name = String(name);
+    return canReadPub(obj, name) ? obj[name] : obj.handleRead___(name);
+  }
+  
+  /**
+   * Can "innocent" code enumerate the named property on this object?
+   * <p>
+   * "Innocent" code is code which we assume to be ignorant of Caja,
+   * not to be actively hostile, but which may be buggy (and
+   * therefore accidentally harmful or exploitable). This
+   * corresponds to legacy code, such as libraries, that we decide
+   * to run untranslated, perhaps hidden or tamed, but which needs
+   * to co-exist smoothly with the Caja runtime.
+   * <p>
+   * An earlier version of canInnocentEnum() filtered out exactly those
+   * names ending with a double underbar. It now filters out exactly
+   * those names ending in a triple underbar. Caja code can't see names
+   * ending in a double underbar, since existing platforms (like
+   * Firefox) use such names for purposes that should be hidden from
+   * Caja code. However, it is not up to Caja to shield innocent code
+   * from seeing such platform properties. All the magic names Caja
+   * adds for its own internal bookkeeping end in triple underbar, so
+   * that is all we need to hide from innocent code.
+   */
+  function canInnocentEnum(obj, name) {
+    name = String(name);
+    if (endsWith(name, '___')) { return false; }
+    return true;
+  }
+  
+  /** 
+   * Would a Caja for/in loop on <tt>this</tt> see this name? 
+   * <p>
+   * For properties defined in Caja, this is generally the same as
+   * canReadProp. Otherwise according to whitelisting.
+   */
+  function canEnumProp(that, name) {
+    name = String(name);
+    if (endsWith(name, '__')) { return false; }
+    return canEnum(that, name);
+  }
+  
+  /** 
+   * Would a Caja for/in loop by a client of obj see this name? 
+   * <p>
+   * For properties defined in Caja, this is generally the same as
+   * canReadProp. Otherwise according to whitelisting.
+   */
+  function canEnumPub(obj, name) {
+    name = String(name);
+    if (endsWith(name, '_')) { return false; }
+    if (canEnum(obj, name)) { return true; }
+    if (!isJSONContainer(obj)) { return false; }
+    if (!hasOwnProp(obj, name)) { return false; }
+    allowEnum(obj, name);  // memoize
+    return true;
+  }
+  
+  /**
+   * Like canEnumPub, but allows only non-inherited properties.
+   */
+  function canEnumOwn(obj, name) {
+    name = String(name);
+    return hasOwnProp(obj, name) && canEnumPub(obj, name);
+  }
+  
+  /**
+   * Inside a <tt>caja.each()</tt>, the body function can terminate
+   * early, as if with a conventional <tt>break;</tt>, by doing a
+   * <pre>return caja.BREAK;</pre>
+   */
+  var BREAK = {};
+  
+  /**
+   * For each sensible key/value pair in obj, call fn with that
+   * pair.
+   * <p>
+   * If <tt>obj instanceof Array</tt>, then enumerate
+   * indexes. Otherwise, enumerate the canEnumOwn() property names.
+   */
+  function each(obj, fn) {
+    fn = asSimpleFunc(fn);
+    if (obj instanceof Array) {
+      var len = obj.length;
+      for (var i = 0; i < len; i++) {
+        if (fn(i, readPub(obj, i)) === BREAK) {
+          return;
+        }
+      }
+    } else {
+      for (var k in obj) {
+        if (canEnumOwn(obj, k)) {
+          if (fn(k, readPub(obj, k)) === BREAK) {
+            return;
+          }
+        }
+      }
+    }
+  }
+  
+  /**
+   * Can this be called as an internal method?
+   * <p>
+   * For genuine methods, they are only callable if the canCall
+   * attribute is set. Otherwise, if this property is readable and
+   * holds a simple function, then it's also callable as a function,
+   * which we can memoize.
+   * <p>
+   * SECURITY HAZARD TODO(erights): If a settable property is
+   * first set to a 
+   * simple function, which is then called, memoizing canCall, and
+   * then set to some other kind of function which leaked (such as
+   * an untamed function), then that other function can be
+   * inappropriately called as a method on that. We currently
+   * classify this as a hazard and not a bug per se, since no such
+   * function value should ever leak into value space. If one does,
+   * there's a bug either in Caja or in the embedding app's taming
+   * decisions.
+   * <p>
+   * In any case, the not-yet-implemented plan to fix this hazard is
+   * to have two canSet flags: one that records the grant of
+   * settability, and one to be tested in the fast-path. The
+   * fast-path canCall and fast-path canSet flags will be exclusive,
+   * to be faulted in by the last successful use. This way, repeated
+   * calls are fast, and repeated sets are fast, but the first call
+   * after a set will re-check the value to be called.
+   * <p>
+   * This plan will need to be thought through again when we
+   * implement property deletion. 
+   */
+  function canCallProp(that, name) {
+    name = String(name);
+    if (endsWith(name, '__')) { return false; }
+    if (canCall(that, name)) { return true; }
+    if (!canReadProp(that, name)) { return false; }
+    var func = that[name];
+    if (!isSimpleFunc(func)) { return false; }
+    allowCall(that, name);  // memoize
+    return true;
+  }
+  
+  /**
+   * A Caja method tries to call one of its Internal methods.
+   */
+  function callProp(that, name, args) {
+    name = String(name);
+    if (canCallProp(that, name)) {
+      var meth = that[name];
+      return meth.apply(that, args);
+    } else {
+      return that.handleCall___(name, args);
+    }
+  }
+  
+  /**
+   * Like canCallProp(), with differences that parallel the
+   * differences between canReadProp vs canReadPub.
+   */
+  function canCallPub(obj, name) {
+    name = String(name);
+    if (endsWith(name, '_')) { return false; }
+    if (canCall(obj, name)) { return true; }
+    if (!canReadPub(obj, name)) { return false; }
+    var func = obj[name];
+    if (!isSimpleFunc(func)) { return false; }
+    allowCall(obj, name);  // memoize
+    return true;
+  }
+  
+  /**
+   * A client of obj tries to call one of its methods.
+   */
+  function callPub(obj, name, args) {
+    name = String(name);
+    if (canCallPub(obj, name)) {
+      var meth = obj[name];
+      return meth.apply(obj, args);
+    } else {
+      return obj.handleCall___(name, args);
+    }
+  }
+  
+  /** 
+   * Can a method of a Caja constructed object directly assign to
+   * this property of its object?
+   * <p>
+   * Iff this object isn't frozen.
+   */
+  function canSetProp(that, name) {
+    name = String(name);
+    if (endsWith(name, '__')) { return false; }
+    if (canSet(that, name)) { return true; }
+    return !isFrozen(that);
+  }
+  
+  /**
+   * A Caja method tries to assign to this property of its object.
+   */
+  function setProp(that, name, val) {
+    name = String(name);
+    if (canSetProp(that, name)) {
+      allowSet(that, name);  // grant
+      that[name] = val;
+      return val;
+    } else {
+      return that.handleSet___(name, val);
+    }
+  }
+  
+  /**
+   * Can a client of obj directly assign to its name property?
+   * <p>
+   * If this property is Internal (i.e., ends with a '_') or if this
+   * object is frozen, then no. 
+   * If this property is not Internal and was defined by Caja code,
+   * then yes. If the object is a JSON container, then
+   * yes. Otherwise according to whitelisting decisions.
+   * <p>
+   * The non-obvious implication of this rule together with the
+   * canSetProp rule is that a Caja client of a Caja constructed
+   * object cannot add new properties to it. But a Caja constructed
+   * object can add new properties to itself, and its clients can
+   * then assign to these properties.
+   */
+  function canSetPub(obj, name) {
+    name = String(name);
+    if (endsWith(name, '_')) { return false; }
+    if (canSet(obj, name)) { return true; }
+    return !isFrozen(obj) && isJSONContainer(obj);
+  }
+  
+  /** A client of obj attempts to assign to one of its properties. */
+  function setPub(obj, name, val) {
+    name = String(name);
+    if (canSetPub(obj, name)) {
+      allowSet(obj, name);  // grant
+      obj[name] = val;
+      return val;
+    } else {
+      return obj.handleSet___(name, val);
+    }
+  }
+  
+  /**
+   * Can a Caja constructed object delete the named property?
+   * <p>
+   * BUG TODO(erights): This is not yet supported. The precise
+   * enabling conditions are not yet determined, as is the implied
+   * bookkeeping. 
+   */
+  function canDeleteProp(that, name) {
+    fail('TODO(erights): deletion not yet supported');
+    return false;
+  }
+  
+  /**
+   * A Caja constructed object attempts to delete one of its own
+   * properties. 
+   * <p>
+   * BUG TODO(erights): This is not yet supported. The precise
+   * enabling conditions are not yet determined, as is the implied
+   * bookkeeping.
+   */
+  function deleteProp(that, name) {
+    name = String(name);
+    if (canDeleteProp(that, name)) {
+      fail('TODO(erights): deletion not yet supported');
+      return (delete that[name]) ||
+        fail('not deleted: ', name);
+    } else {
+      return that.handleDelete___(name);
+    }
+  }
+  
+  /**
+   * Can a client of obj delete the named property?
+   * <p>
+   * BUG TODO(erights): This is not yet supported. The precise
+   * enabling conditions are not yet determined, as is the implied
+   * bookkeeping. 
+   */
+  function canDeletePub(obj, name) {
+    fail('TODO(erights): deletion not yet supported');
+    return false;
+  }
+  
+  /**
+   * A client of obj can only delete a property of obj if obj is a
+   * non-frozen JSON container.
+   * <p>
+   * BUG TODO(erights): This is not yet supported. The precise
+   * enabling conditions are not yet determined, as is the implied
+   * bookkeeping. 
+   */
+  function deletePub(obj, name) {
+    name = String(name);
+    if (canDeletePub(obj, name)) {
+      if (!isJSONContainer(obj)) {
+        fail('unable to delete: ', name);
+      }
+      fail('TODO(erights): deletion not yet supported');
+      return (delete obj[name]) ||
+        fail('not deleted: ', name);
+    } else {
+      return obj.handleDelete___(name);
+    }
+  }
+  
+  ////////////////////////////////////////////////////////////////////////
+  // Other
+  ////////////////////////////////////////////////////////////////////////
+  
+  /**
+   * This returns a frozen array copy of the original array or
+   * array-like object.
+   * <p>
+   * If a Caja program makes use of <tt>arguments</tt> in any
+   * position other than <tt>arguments.callee</tt>, this is
+   * rewritten to use a frozen array copy of arguments instead. This
+   * way, if Caja code passes its arguments to someone else, they
+   * are not giving the receiver the rights to access the passing
+   * function nor to modify the parameter variables of the passing
+   * function.
+   */
+  function args(original) {
+    return primFreeze(Array.prototype.slice.call(original, 0));
+  }
+  
+  /**
+   *
+   */
+  function setMemberMap(sub, members) {
+    each(members, simpleFunc(function(mname, member) {
+      setMember(sub, mname, member);
+    }));
+  }
+  
+  /**
+   * Provides a shorthand for a class-like declaration of a fresh
+   * Caja constructor.
+   * <p>
+   * Given that sub is a Caja constructor in formation, whose 'prototype'
+   * property hasn't been initialized yet, initialize sub and its
+   * 'prototype' property so that it acts as a subclass of opt_Sup,
+   * with opt_members added as members to sub.prototype, and
+   * opt_statics added as members to sub.
+   * <p>
+   * TODO(erights): return a builder object that allows further
+   * initialization. 
+   */
+  function def(sub, opt_Sup, opt_members, opt_statics) {
+    var sup = opt_Sup || Object;
+    var members = opt_members || {};
+    var statics = opt_statics || {};
+    if ('Super' in statics) {
+      fail('The static name "Super" is reserved ',
+           'for the super-constructor');
+    }
+    
+    ctor(sub, sup);
+    function PseudoSuper() {}
+    PseudoSuper.prototype = sup.prototype;
+    sub.prototype = new PseudoSuper();
+    sub.prototype.constructor = sub;
+    
+    setMemberMap(sub, members);
+    each(statics, simpleFunc(function(sname, staticMember) {
+      setPub(sub, sname, staticMember);
+    }));
+    
+    // translator freezes sub and sub.prototype later.
+  }
+  
+  ////////////////////////////////////////////////////////////////////////
+  // Taming mechanism
+  ////////////////////////////////////////////////////////////////////////
+
+  /**
+   * Arrange to handle read-faults on <tt>obj[name]</tt>
+   * by calling <tt>getHandler()</tt> as a method on the faulted
+   * object. 
+   * <p>
+   * In order for this fault-handler to get control, it's important
+   * that no one does a conflicting allowRead().
+   */
+  function useGetHandler(obj, name, getHandler) {
+    obj[name + '_getter___'] = getHandler;
+  }
+
+  /**
+   * Arrange to handle call-faults on <tt>obj[name](args...)</tt> by
+   * calling <tt>applyHandler(args)</tt> as a method on the faulted
+   * object. 
+   * <p>
+   * Note that <tt>applyHandler</tt> is called with a single argument,
+   * which is the list of arguments in the original call.
+   * <p>
+   * In order for this fault-handler to get control, it's important
+   * that no one does a conflicting allowCall(), allowSimpleFunc(), or
+   * allowMethod().
+   */
+  function useApplyHandler(obj, name, applyHandler) {
+    obj[name + '_handler___'] = applyHandler;
+  }
+
+  /**
+   * Arrange to handle call-faults on <tt>obj[name](args...)</tt> by
+   * calling <tt>callHandler(args...)</tt> as a method on the faulted
+   * object. 
+   * <p>
+   * Note that <tt>callHandler</tt> is called with the same arguments
+   * as the original call. 
+   * <p>
+   * In order for this fault-handler to get control, it's important
+   * that no one does a conflicting allowCall(), allowSimpleFunc(), or
+   * allowMethod().
+   */
+  function useCallHandler(obj, name, callHandler) {
+    useApplyHandler(obj, name, function(args) {
+      return callHandler.apply(this, args);
+    });
+  }
+
+  /**
+   * Arrange to handle set-faults on <tt>obj[name] = newValue</tt> by
+   * calling <tt>setHandler(newValue)</tt> as a method on the faulted
+   * object.  
+   * <p>
+   * In order for this fault-handler to get control, it's important
+   * that no one does a conflicting allowSet().
+   */
+  function useSetHandler(obj, name, setHandler) {
+    obj[name + '_setter___'] = setHandler;
+  }
+
+  /**
+   * Arrange to handle delete-faults on <tt>delete obj[name]</tt> by
+   * calling <tt>deleteHandler()</tt> as a method on the faulted object. 
+   * <p>
+   * In order for this fault-handler to get control, it's important
+   * that no one does a conflicting allowDelete().
+   */
+  function useDeleteHandler(obj, name, deleteHandler) {
+    obj[name + '_deleter___'] = deleteHandler;
+  }
+
+  /**
+   * Whilelist obj[name] as a simple function that can be either
+   * called or read.
+   */
+  function allowSimpleFunc(obj, name) {
+    simpleFunc(obj[name], name);
+    allowCall(obj, name);
+    allowRead(obj, name);
+  }
+  
+  /**
+   * Whitelist constr.prototype[name] as a method that can be called
+   * on instances of constr.
+   */
+  function allowMethod(constr, name) {
+    method(constr, constr.prototype[name], name);
+    allowCall(constr.prototype, name);
+  }
+  
+  /**
+   * Virtually replace constr.prototype[name] with a fault-handler
+   * wrapper that first verifies that <tt>this</tt> isn't frozen.
+   * <p>
+   * When a pre-existing Javascript method would mutate its object,
+   * we need to provide a fault handler instead to prevent such
+   * mutation from violating Caja semantics. In order for this fault
+   * handler to get control, it's important that no one does an
+   * allowCall(), allowSimpleFunc(), or allowMethod() on the
+   * original method. 
+   */
+  function allowMutator(constr, name) {
+    var original = constr.prototype[name];
+    useApplyHandler(constr.prototype, name, function(args) {
+      if (isFrozen(this)) {
+        fail("Can't .", name, ' a frozen object');
+      }
+      return original.apply(this, args);
+    });
+  }
+  
+  /**
+   * Verifies that regexp is something that can appear as a
+   * parameter to a Javascript method that would use it in a match.
+   * <p>
+   * If it is a RegExp, then this match might mutate it, which must
+   * not be allowed if regexp is frozen.
+   */
+  function enforceMatchable(regexp) {
+    if (regexp instanceof RegExp) {
+      if (isFrozen(regexp)) {
+        fail("Can't match with frozen RegExp: ", regexp);
+      }
+    }
+  }
+  
+  /**
+   * A shorthand that happens to be useful here.
+   * <p>
+   * For all i in arg2s: func2(arg1,arg2s[i]).
+   */
+  function all2(func2, arg1, arg2s) {
+    var len = arg2s.length;
+    for (var i = 0; i < len; i += 1) {
+      func2(arg1, arg2s[i]);
+    }
+  }
+  
+  ////////////////////////////////////////////////////////////////////////
+  // Taming decisions
+  ////////////////////////////////////////////////////////////////////////
+
+
+  all2(allowRead, Math, [
+    'E', 'LN10', 'LN2', 'LOG2E', 'LOG10E', 'PI', 'SQRT1_2', 'SQRT2'
+  ]);
+  all2(allowSimpleFunc, Math, [
+    'abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor',
+    'log', 'max', 'min', 'pow', 'random', 'round', 'sin', 'sqrt', 'tan'
+  ]);
+  
+  
+  ctor(Object, undefined, 'Object');
+  all2(allowMethod, Object, [
+    'toString', 'toLocaleString', 'valueOf', 'isPrototypeOf'
+  ]);
+  allowRead(Object.prototype, 'length');
+  useCallHandler(Object.prototype, 'hasOwnProperty',  function(name) {
+    name = String(name);
+    return canReadPub(this, name) && hasOwnProp(this, name);
+  });
+  var pie_ = Object.prototype.propertyIsEnumerable;
+  useCallHandler(Object.prototype, 'propertyIsEnumerable', function(name) {
+    name = String(name);
+    return canReadPub(this, name) && pie_.call(this, name);
+  });
+
+
+  /**
+   * A method of a constructed object can freeze its object by saying
+   * <tt>this.freeze_()</tt>.
+   * <p>
+   * Because this method ends in a "_", it is internal, so clients
+   * of a constructed object (a non-JSON container) cannot freeze it
+   * without its cooperation.
+   */
+  useCallHandler(Object.prototype, 'freeze_', function() {
+    return primFreeze(this);
+  });
+  
+  
+  // SECURITY HAZARD TODO(erights): Seems dangerous, but doesn't add
+  // risk. Or does it? 
+  ctor(Function, Object, 'Function');
+  // SECURITY HAZARD TODO(erights): Seems dangerous, but doesn't add
+  // risk. Or does it? 
+  allowRead(Function.prototype, 'prototype');
+
+  useCallHandler(Function.prototype, 'apply', function(that, realArgs) {
+    return asSimpleFunc(this).apply(that, realArgs[0]);
+  });
+  useCallHandler(Function.prototype, 'call', function(that, realArgs) {
+    return asSimpleFunc(this).apply(that, realArgs);
+  });
+  
+  
+  ctor(Array, Object, 'Array');
+  all2(allowMethod, Array, [
+    'concat', 'join', 'slice', 'indexOf', 'lastIndexOf'
+  ]);
+  all2(allowMutator, Array, [
+    'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'
+  ]);
+  
+  
+  ctor(String, Object, 'String');
+  allowSimpleFunc(String, 'fromCharCode');
+  all2(allowMethod, String, [
+    'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf',
+    'localeCompare', 'slice', 'substring',
+    'toLowerCase', 'toLocaleLowerCase', 'toUpperCase', 'toLocaleUpperCase'
+  ]);
+  useCallHandler(String.prototype, 'match', function(regexp) {
+    enforceMatchable(regexp);
+    return this.match(regexp);
+  });
+  useCallHandler(String.prototype, 'replace', function(searchValue, 
+                                                       replaceValue) {
+    enforceMatchable(searchValue);
+    return this.replace(searchValue, replaceValue);
+  });
+  useCallHandler(String.prototype, 'search', function(regexp) {
+    enforceMatchable(regexp);
+    return this.search(regexp);
+  });
+  useCallHandler(String.prototype, 'split', function(separator, limit) {
+    enforceMatchable(separator);
+    return this.split(separator, limit);
+  });
+  
+  
+  ctor(Boolean, Object, 'Boolean');
+  
+  
+  ctor(Number, Object, 'Number');
+  all2(allowRead, Number, [
+    'MAX_VALUE', 'MIN_VALUE', 'NaN',
+    'NEGATIVE_INFINITY', 'POSITIVE_INFINITY'
+  ]);
+  all2(allowMethod, Number, [
+    'toFixed', 'toExponential', 'toPrecision'
+  ]);
+  
+  
+  ctor(Date, Object, 'Date');
+  allowSimpleFunc(Date, 'parse');
+  allowSimpleFunc(Date, 'UTC');
+  
+  all2(allowMethod, Date, [
+    'toDateString', 'toTimeString', 'toUTCString',
+    'toLocaleString', 'toLocaleDateString', 'toLocaleTimeString',
+    'toISOString',
+    'getDay', 'getUTCDay', 'getTimezoneOffset',
+    
+    'getTime', 'getFullYear', 'getUTCFullYear', 'getMonth', 'getUTCMonth',
+    'getDate', 'getUTCDate', 'getHours', 'getUTCHours',
+    'getMinutes', 'getUTCMinutes', 'getSeconds', 'getUTCSeconds',
+    'getMilliseconds', 'getUTCMilliseconds'
+  ]);
+  all2(allowMutator, Date, [
+    'setTime', 'setFullYear', 'setUTCFullYear', 'setMonth', 'setUTCMonth',
+    'setDate', 'setUTCDate', 'setHours', 'setUTCHours',
+    'setMinutes', 'setUTCMinutes', 'setSeconds', 'setUTCSeconds',
+    'setMilliseconds', 'setUTCMilliseconds'
+  ]);
+  
+  
+  ctor(RegExp, Object, 'RegExp');
+  allowMutator(RegExp, 'exec');
+  allowMutator(RegExp, 'test');
+  
+  all2(allowRead, RegExp, [
+    'source', 'global', 'ignoreCase', 'multiline', 'lastIndex'
+  ]);
+  
+  
+  ctor(Error, Object, 'Error');
+  allowRead(Error, 'name');
+  allowRead(Error, 'message');
+  ctor(EvalError, Error, 'EvalError');
+  ctor(RangeError, Error, 'RangeError');
+  ctor(ReferenceError, Error, 'ReferenceError');
+  ctor(SyntaxError, Error, 'SyntaxError');
+  ctor(TypeError, Error, 'TypeError');
+  ctor(URIError, Error, 'URIError');
+  
+  
+  var sharedOuters;
+  
+  ////////////////////////////////////////////////////////////////////////
+  // Module loading
+  ////////////////////////////////////////////////////////////////////////
+  
+  var myNewModuleHandler;
+  
+  /**
+   * Gets the current module handler.
+   */
+  function getNewModuleHandler() {
+    return myNewModuleHandler;
+  }
+  
+  /**
+   * Registers a new-module-handler, to be called back when a new
+   * module is loaded.
+   * <p>
+   * This callback mechanism is provided so that translated Caja
+   * modules can be loaded from a trusted site with the
+   * &lt;script&gt; tag, which runs its script as a statement, not
+   * an expression. The callback is of the form
+   * <tt>moduleHandler.handle(newModule)</tt>.
+   */
+  function setNewModuleHandler(newModuleHandler) {
+    myNewModuleHandler = newModuleHandler;
+  }
+  
+  /**
+   * A new-module-handler which does nothing.
+   */
+  var ignoreNewModule = freeze({
+    handle: simpleFunc(function(newModule){})
+  });
+  
+  /**
+   * Makes and returns a fresh "normal" module handler whose outers
+   * are initialized to a copy of the sharedOuters.
+   * <p>
+   * This handles a new module by calling it, passing it the outers
+   * object held in this handler. Successive modules handled by the
+   * same "normal" handler thereby see a simulation of successive
+   * updates to a shared global scope.
+   */
+  function makeNormalNewModuleHandler() {
+    var outers = copy(sharedOuters);
+    return freeze({
+      getOuters: simpleFunc(function() { return outers; }),
+      setOuters: simpleFunc(function(newOuters) { outers = newOuters; }),
+      handle: simpleFunc(function(newModule) {
+        newModule(outers);
+      })
+    });
+  }
+  
+  /**
+   * A module is a plugin-maker function.
+   * <p>
+   * loadModule(module) marks module as a simpleFunc, freezes it,
+   * asks the current new-module-handler to handle it (thereby
+   * notifying the handler), and returns the new module.  
+   */
+  function loadModule(module) {
+    callPub(myNewModuleHandler, 'handle',
+            [primFreeze(simpleFunc(module))]);
+    return module;
+  }
+
+  var registeredOuters = [];
+
+  /**
+   * Gets or assigns the id associated with this (assumed to be)
+   * outers object, registering it so that 
+   * <tt>getOuters(getId(outers)) ==== outers</tt>.
+   * <p>
+   * This system of registration and identification allows us to
+   * cajole html such as
+   * <pre>&lt;a onmouseover="alert(1)"&gt;Mouse here&lt;/a&gt;</pre>
+   * into html-writing JavaScript such as<pre>
+   * ___OUTERS___.document.innerHTML = "
+   *  &lt;a onmouseover=\"
+   *    (function(___OUTERS___) {
+   *      ___OUTERS___.alert(1);
+   *    })(___.getOuters(" + ___.getId(___OUTERS___) + "))
+   *  \"&gt;Mouse here&lt;/a&gt;
+   * ";
+   * </pre>
+   * If this is executed by a plugin whose outers is assigned id 42,
+   * it generates html with the same meaning as<pre>
+   * &lt;a onmouseover="___.getOuters(42).alert(1)"&gt;Mouse here&lt;/a&gt;
+   * </pre>
+   * <p>
+   * An outers is not registered and no id is assigned to it until the
+   * first call to <tt>getId</tt>. This way, an outers that is never
+   * registered, or that has been <tt>unregister</tt>ed since the last
+   * time it was registered, will still be garbage collectable.
+   */
+  function getId(outers) {
+    enforceType(outers, 'object', 'outers');
+    var id;
+    if ('id___' in outers) {
+      id = enforceType(outers.id___, 'number', 'id');
+    } else {
+      id = outers.id___ = registeredOuters.length;
+    }
+    registeredOuters[id] = outers;
+    return id;
+  }
+
+  /**
+   * Gets the outers object registered under this id.
+   * <p>
+   * If it has been <tt>unregistered</tt> since the last
+   * <tt>getId</tt> on it, then <tt>getOuters</tt> will fail.
+   */
+  function getOuters(id) {
+    var result = registeredOuters[enforceType(id, 'number', 'id')];
+    if (result === undefined) {
+      fail('outers#', id, ' unregistered');
+    }
+    return result;
+  }
+
+  /**
+   * If you know that this <tt>outers</tt> no longers needs to be
+   * accessed by <tt>getOuters</tt>, then you should
+   * <tt>unregister</tt> it so it can be garbage collected.
+   * <p>
+   * After unregister()ing, the id is not reassigned, and the outers
+   * remembers its id. If asked for another <tt>getId</tt>, it
+   * reregisters itself at its old id.
+   */
+  function unregister(outers) {
+    enforceType(outers, 'object', 'outers');      
+    if ('id___' in outers) {
+      var id = enforceType(outers.id___, 'number', 'id');
+      registeredOuters[id] = undefined;
+    }
+  }
+  
+  ////////////////////////////////////////////////////////////////////////
+  // Exports
+  ////////////////////////////////////////////////////////////////////////
+  
+  caja = {
+
+    // Diagnostics and condition enforcement
+    getLogFunc: getLogFunc, 
+    setLogFunc: setLogFunc,
+    log: log,
+
+    fail: fail,
+    enforce: enforce,
+    enforceType: enforceType,
+    enforceNat: enforceNat,
+    
+    // walking prototype chain, checking JSON containers
+    isJSONContainer: isJSONContainer,
+    freeze: freeze,
+    copy: copy,
+    snapshot: snapshot,
+    
+    // Accessing properties
+    canReadPub: canReadPub,       readPub: readPub,
+    canEnumPub: canEnumPub,
+    canEnumOwn: canEnumOwn,       
+    BREAK: BREAK,                 each: each,                   
+    canCallPub: canCallPub,       callPub: callPub,
+    canSetPub: canSetPub,         setPub: setPub,
+    canDeletePub: canDeletePub,   deletePub: deletePub,
+    
+    // Other
+    def: def
+  };
+  
+  sharedOuters = {
+    caja: caja,
+    
+    'null': null,
+    'false': false,
+    'true': true,
+    'NaN': NaN,
+    'Infinity': Infinity,
+    'undefined': undefined,
+    parseInt: parseInt,
+    parseFloat: parseFloat,
+    isNaN: isNaN,
+    isFinite: isFinite,
+    decodeURI: decodeURI,
+    decodeURIComponent: decodeURIComponent,
+    encodeURI: encodeURI,
+    encodeURIComponent: encodeURIComponent,
+    Math: Math,
+    
+    Object: Object,
+    Array: Array,
+    String: String,
+    Boolean: Boolean,
+    Number: Number,
+    Date: Date,
+    RegExp: RegExp,
+    
+    Error: Error,
+    EvalError: EvalError,
+    RangeError: RangeError,
+    ReferenceError: ReferenceError,
+    SyntaxError: SyntaxError,
+    TypeError: TypeError,
+    URIError: URIError
+  };
+  
+  each(sharedOuters, simpleFunc(function(k, v) {
+    switch (typeof v) {
+    case 'object':
+      if (v !== null) { primFreeze(v); }
+      break;
+    case 'function':
+      primFreeze(v);
+      break;
+    }
+  }));
+  primFreeze(sharedOuters);
+  
+  ___ = {
+
+    // Privileged fault handlers
+    getKeeper: getKeeper,
+    setKeeper: setKeeper,
+
+    // walking prototype chain, checking JSON containers
+    directConstructor: directConstructor,
+    isFrozen: isFrozen,
+    primFreeze: primFreeze,
+    
+    // Accessing property attributes
+    canRead: canRead,             allowRead: allowRead,
+    canEnum: canEnum,             allowEnum: allowEnum,
+    canCall: canCall,             allowCall: allowCall,
+    canSet: canSet,               allowSet: allowSet,
+    canDelete: canDelete,         allowDelete: allowDelete,
+    
+    // Classifying functions
+    isCtor: isCtor,
+    isMethod: isMethod,
+    isSimpleFunc: isSimpleFunc,
+    ctor: ctor,                   asCtorOnly: asCtorOnly,
+    asCtor: asCtor,
+    method: method,               asMethod: asMethod,
+    simpleFunc: simpleFunc,       asSimpleFunc: asSimpleFunc,
+    setMember: setMember,
+    setMemberMap: setMemberMap,
+    
+    // Accessing properties
+    canReadProp: canReadProp,     readProp: readProp,
+    canInnocentEnum: canInnocentEnum,
+    canEnumProp: canEnumProp,
+    canCallProp: canCallProp,     callProp: callProp,
+    canSetProp: canSetProp,       setProp: setProp,
+    canDeleteProp: canDeleteProp, deleteProp: deleteProp,
+    
+    // Other
+    hasOwnProp: hasOwnProp,
+    args: args,
+    
+    // Taming mechanism
+    useGetHandler: useGetHandler, 
+    useApplyHandler: useApplyHandler,
+    useCallHandler: useCallHandler,
+    useSetHandler: useSetHandler,
+    useDeleteHandler: useDeleteHandler,
+
+    allowSimpleFunc: allowSimpleFunc,
+    allowMethod: allowMethod,
+    allowMutator: allowMutator,
+    enforceMatchable: enforceMatchable,
+    all2: all2,
+    
+    // Taming decisions
+    sharedOuters: sharedOuters,
+    
+    // Module loading
+    getNewModuleHandler: getNewModuleHandler,
+    setNewModuleHandler: setNewModuleHandler,
+    ignoreNewModule: ignoreNewModule,
+    makeNormalNewModuleHandler: makeNormalNewModuleHandler,
+    loadModule: loadModule,
+
+    getId: getId,
+    getOuters: getOuters,
+    unregister: unregister
+  };
+  
+  each(caja, simpleFunc(function(k, v) {
+    if (k in ___) {
+      fail('internal: initialization conflict: ', k);
+    }
+    if (typeof v === 'function') {
+      simpleFunc(v);
+      allowCall(caja, k);
+    }
+    ___[k] = v;
+  }));
+  primFreeze(caja);
+  
+  setNewModuleHandler(makeNormalNewModuleHandler());
+  
+})(this);

Propchange: incubator/shindig/trunk/features/caja/caja.js
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/shindig/trunk/features/caja/feature.xml
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/caja/feature.xml?rev=610628&view=auto
==============================================================================
--- incubator/shindig/trunk/features/caja/feature.xml (added)
+++ incubator/shindig/trunk/features/caja/feature.xml Wed Jan  9 17:17:56 2008
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!--
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+  TODO(doll): The caja.js file referenced here should come from maven 
+  or something. We should not have our own copy of it.
+-->
+<feature>
+  <name>caja</name>
+  <gadget>
+    <script src="caja.js"/>
+  </gadget>
+</feature>

Added: incubator/shindig/trunk/features/opensocial-reference/activity.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/opensocial-reference/activity.js?rev=610628&view=auto
==============================================================================
--- incubator/shindig/trunk/features/opensocial-reference/activity.js (added)
+++ incubator/shindig/trunk/features/opensocial-reference/activity.js Wed Jan  9 17:17:56 2008
@@ -0,0 +1,308 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @fileoverview Representation of an activity.
+ */
+
+
+/**
+ * @class
+ * Base interface for all activity objects.
+ *
+ * <p>
+ * <b>See also:</b>
+ * <a href="opensocial.html#newActivity">opensocial.newActivity()</a>,
+ * <a href="opensocial.html#requestCreateActivity">
+ * opensocial.requestCreateActivity()</a>
+ *
+ * @name opensocial.Activity
+ */
+
+
+/**
+ * Base interface for all activity objects.
+ *
+ * @param {opensocial.Activity.Template || String} title The title of an
+ *     activity; a template is recommended, but this field can also be a
+ *     string.
+ * @param {Map.<opensocial.Activity.Field, Object>} opt_params Any other
+ *    fields that should be set on the activity object. All of the defined
+ *    Fields are supported.
+ * @private
+ * @constructor
+ */
+opensocial.Activity = function(title, opt_params) {
+  this.fields_ = opt_params || {};
+  this.fields_[opensocial.Activity.Field.TITLE] = title;
+};
+
+
+/**
+ * @static
+ * @class
+ * All of the fields that activities can have.
+ *
+ * <p>
+ * <b>See also:</b>
+ * <a
+ * href="opensocial.Activity.html#getField">opensocial.Activity.getField()</a>
+ * </p>
+ *
+ * @name opensocial.Activity.Field
+ */
+opensocial.Activity.Field = {
+  /**
+   * A string ID
+   * that can be permanently associated with this activity.
+   * @member opensocial.Activity.Field
+   */
+  ID : 'id',
+
+  /**
+   * A string ID
+   * associated with this activity that was generated by the
+   * posting app externally.
+   * @member opensocial.Activity.Field
+   */
+  EXTERNAL_ID : 'externalId',
+
+  /**
+   * The string ID of the user who this activity is for.
+   * @member opensocial.Activity.Field
+   */
+  USER_ID : 'userId',
+
+  /**
+   * A string specifying the application that this activity is associated with.
+   * @member opensocial.Activity.Field
+   */
+  APP_ID : 'appId',
+
+  /**
+   * A string specifing the title of the stream.
+   * @member opensocial.Activity.Field
+   */
+  STREAM_TITLE : 'streamTitle',
+
+  /**
+   * A string specifying the stream's URL.
+   * @member opensocial.Activity.Field
+   */
+  STREAM_URL : 'streamUrl',
+
+  /**
+   * A string specifying the stream's source URL.
+   * @member opensocial.Activity.Field
+   */
+  STREAM_SOURCE_URL : 'streamSourceUrl',
+
+  /**
+   * A string specifying the URL for the stream's favicon.
+   * @member opensocial.Activity.Field
+   */
+  STREAM_FAVICON_URL : 'streamFaviconUrl',
+
+  /**
+   * A string specifying the title of an activity;
+   * the only field that is guaranteed
+   * to display when rendering.
+   * @member opensocial.Activity.Field
+   */
+  TITLE : 'title',
+
+  /**
+   * A string specifying the full text of an activity.
+   * @member opensocial.Activity.Field
+   */
+  BODY : 'body',
+
+  /**
+   * A string specifying the
+   * URL that represents this activity.
+   * @member opensocial.Activity.Field
+   */
+  URL : 'url',
+
+  /**
+   * Any photos, videos, or images that should be associated
+   * with the activity. Higher priority ones are higher in the list.
+   * The data has type <code>Array&lt;
+   * <a href="opensocial.Activity.MediaItem.html">MediaItem</a>&gt;</code>.
+   * @member opensocial.Activity.Field
+   */
+  MEDIA_ITEMS : 'mediaItems',
+
+  /**
+   * A string specifying the time at which this activity took place
+   * in milliseconds since the epoch.
+   * @member opensocial.Activity.Field
+   */
+  POSTED_TIME : 'postedTime',
+
+  /**
+   * A map of custom keys to values associated with this activity.
+   * @private - not supported until templates exist
+   * The data has type <code>Map&lt;String, String&gt;</code>.
+   * @member opensocial.Activity.Field
+   */
+  CUSTOM_VALUES : 'customValues'
+};
+
+
+/**
+ * Gets an ID that can be permanently associated with this activity.
+ *
+ * @return {String} The ID
+ * @member opensocial.Activity
+ */
+opensocial.Activity.prototype.getId = function() {
+  return this.getField(opensocial.Activity.Field.ID);
+};
+
+
+/**
+ * Gets the activity data that's associated with the specified key.
+ *
+ * @param {String} key The key to get data for;
+ *   see the <a href="opensocial.Activity.Field.html">Field</a> class
+ * for possible values
+ * @return {String} The data
+ * @member opensocial.Activity
+ */
+opensocial.Activity.prototype.getField = function(key) {
+  return this.fields_[key];
+};
+
+
+/**
+ * Sets data for this activity associated with the given key.
+ *
+ * @param {String} key The key to set data for
+ * @param {String} data The data to set
+ */
+opensocial.Activity.prototype.setField = function(key, data) {
+  return this.fields_[key] = data;
+};
+
+
+/**
+ * @class
+ * A media item associated with an activity.
+ * Represents images, movies, and audio.
+ * Create a <code>MediaItem</code> object using the
+ * <a href="opensocial.html#newActivityMediaItem">
+ * opensocial.newActivityMediaItem()</a> method.
+ *
+ * @name opensocial.Activity.MediaItem
+ */
+
+/**
+ * A media item associated with an activity. Represents images, movies, and
+ * audio.
+ *
+ * @param {String} mimetype The media's type
+ * @param {String} url The media's location
+ * @param {Map.<opensocial.Activity.MediaItem.Field, Object>} opt_params
+ *    Any other fields that should be set on the media item object.
+ *    All of the defined Fields are supported.
+ * @constructor
+ * @private
+ */
+opensocial.Activity.MediaItem = function(mimeType, url, opt_params) {
+  this.fields_ = opt_params || {};
+  this.fields_[opensocial.Activity.MediaItem.Field.MIME_TYPE] = mimeType;
+  this.fields_[opensocial.Activity.MediaItem.Field.URL] = url;
+};
+
+
+/**
+ * @static
+ * @class
+ * The possible types of media items.
+ *
+ * <p>
+ * <b>See also:</b>
+ * <a href="opensocial.Activity.MediaItem.Field.html">
+ * opensocial.Activity.MediaItem.Field</a>
+ * </p>
+ *
+ * @name opensocial.Activity.MediaItem.Type = {
+ */
+opensocial.Activity.MediaItem.Type = {
+  /** @member opensocial.Activity.MediaItem.Type */
+  IMAGE : 'image',
+  /** @member opensocial.Activity.MediaItem.Type */
+  VIDEO : 'video',
+  /** @member opensocial.Activity.MediaItem.Type */
+  AUDIO : 'audio'
+}
+
+
+/**
+ * @static
+ * @class
+ * All of the fields that media items have.
+ *
+ * <p>
+ * <b>See also:</b>
+ * <a href="opensocial.Activity.MediaItem.html#getField">
+ * opensocial.Activity.MediaItem.getField()</a>
+ * </p>
+ *
+ * @name opensocial.Activity.MediaItem.Field
+ */
+opensocial.Activity.MediaItem.Field = {
+  /**
+   * The type of media, specified as a
+   * <a href="opensocial.Activity.MediaItem.Type.html">
+   * <code>MediaItem.Type</code></a> object.
+   * @member opensocial.Activity.MediaItem.Field
+   */
+  TYPE : 'type',
+
+  /**
+   * The MIME type of media, specified as a String.
+   * @member opensocial.Activity.MediaItem.Field
+   */
+  MIME_TYPE : 'mimeType',
+
+  /**
+   * A string specifying the URL where the media can be found.
+   * @member opensocial.Activity.MediaItem.Field
+   */
+  URL : 'url'
+};
+
+
+/**
+ * Gets the media item data that's associated with the specified key.
+ *
+ * @param {String} key The key to get data for; see the
+ *   <a href="opensocial.Activity.MediaItem.Field.html">Field</a> class
+ *   for possible values
+ * @return {String} The data
+ */
+opensocial.Activity.MediaItem.prototype.getField = function(key) {
+  return this.fields_[key];
+};
+
+
+/**
+ * Sets data for this media item associated with the given key.
+ *
+ * @param {String} key The key to set data for
+ * @param {String} data The data to set
+ */
+opensocial.Activity.MediaItem.prototype.setField = function(key, data) {
+  return this.fields_[key] = data;
+};

Propchange: incubator/shindig/trunk/features/opensocial-reference/activity.js
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/shindig/trunk/features/opensocial-reference/collection.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/opensocial-reference/collection.js?rev=610628&view=auto
==============================================================================
--- incubator/shindig/trunk/features/opensocial-reference/collection.js (added)
+++ incubator/shindig/trunk/features/opensocial-reference/collection.js Wed Jan  9 17:17:56 2008
@@ -0,0 +1,112 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @fileoverview Collection of multiple objects with useful accessors.
+ *
+ * May also represent subset of a larger collection (i.e. page 1 of 10), and
+ * contain information about the larger collection.
+ */
+
+
+/**
+ * @class
+ * Collection of multiple objects with useful accessors.
+ * May also represent subset of a larger collection
+ * (for example, page 1 of 10)
+ * and contain information about the larger collection.
+ *
+ * @name opensocial.Collection
+ */
+
+
+/**
+ * Create a collection.
+ *
+ * @private
+ * @constructor
+ */
+opensocial.Collection = function(array, opt_offset, opt_totalSize) {
+  this.array_ = array || [];
+  this.offset_ = opt_offset || 0;
+  this.totalSize_ = opt_totalSize || this.array_.length;
+};
+
+
+/**
+ * Finds the entry with the given ID value, or returns null if none is found.
+ * @param {String} id The ID to look for
+ * @return {Object?} The data
+ */
+opensocial.Collection.prototype.getById = function(id) {
+   // TODO(doll): A non-linear search would be better
+  for (var i = 0; i < this.size(); i++) {
+    var item = this.array_[i];
+    if (item.getId() == id) {
+      return item;
+    }
+  }
+
+  return null;
+};
+
+
+/**
+ * Gets the size of this collection,
+ * which is equal to or less than the
+ * total size of the result.
+ * @return {Number} The size of this collection
+ */
+opensocial.Collection.prototype.size = function() {
+  return this.array_.length;
+};
+
+
+/**
+ * Executes the provided function once per member of the collection,
+ * with each member in turn as the
+ * parameter to the function.
+ * @param {Function} fn The function to call with each collection entry
+ */
+opensocial.Collection.prototype.each = function(fn) {
+  for (var i = 0; i < this.size(); i++) {
+    fn(this.array_[i]);
+  }
+};
+
+
+/**
+ * Returns an array of all the objects in this collection.
+ * @return {Array.&lt;Object&gt;} The values in this collection
+ */
+opensocial.Collection.prototype.asArray = function() {
+  return this.array_;
+};
+
+
+/**
+ * Gets the total size of the larger result set
+ * that this collection belongs to.
+ * @return {Number} The total size of the result
+ */
+opensocial.Collection.prototype.getTotalSize = function() {
+  return this.totalSize_;
+};
+
+
+/**
+ * Gets the offset of this collection within a larger result set.
+ * @return {Number} The offset into the total collection
+ */
+opensocial.Collection.prototype.getOffset = function() {
+  return this.offset_;
+};

Propchange: incubator/shindig/trunk/features/opensocial-reference/collection.js
------------------------------------------------------------------------------
    svn:executable = *



Re: svn commit: r610628 [1/2] - in /incubator/shindig/trunk: features/caja/ features/opensocial-reference/ features/opensocial-samplecontainer/ javascript/opensocial/

Posted by Cassie <do...@apache.org>.
Thank Vincent - my svn skills are not quite up to par yet - thankfully the
files didn't have much history to them this time.
I'll remember to do so in the future.

- Cassie


On Jan 10, 2008 3:32 AM, Vincent Siveton <vi...@gmail.com> wrote:

> Hi,
>
> 2008/1/9, doll@apache.org <do...@apache.org>:
> > Author: doll
> > Date: Wed Jan  9 17:17:56 2008
> > New Revision: 610628
> >
> > URL: http://svn.apache.org/viewvc?rev=610628&view=rev
> > Log:
> > - Moved the opensocial reference code into the new features directory.
>
> [SNIP]
>
> > Removed:
> >     incubator/shindig/trunk/javascript/opensocial/
>
> FYI a good SVN practice in ASF land is to use "svn move" when moving
> existing files. This ensures that the history of the files is not
> lost.
>
> Cheers,
>
> Vincent
>
> [SNIP]
>

Re: svn commit: r610628 [1/2] - in /incubator/shindig/trunk: features/caja/ features/opensocial-reference/ features/opensocial-samplecontainer/ javascript/opensocial/

Posted by Vincent Siveton <vi...@gmail.com>.
Hi,

2008/1/9, doll@apache.org <do...@apache.org>:
> Author: doll
> Date: Wed Jan  9 17:17:56 2008
> New Revision: 610628
>
> URL: http://svn.apache.org/viewvc?rev=610628&view=rev
> Log:
> - Moved the opensocial reference code into the new features directory.

[SNIP]

> Removed:
>     incubator/shindig/trunk/javascript/opensocial/

FYI a good SVN practice in ASF land is to use "svn move" when moving
existing files. This ensures that the history of the files is not
lost.

Cheers,

Vincent

[SNIP]