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
+ * <script> 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><a onmouseover="alert(1)">Mouse here</a></pre>
+ * into html-writing JavaScript such as<pre>
+ * ___OUTERS___.document.innerHTML = "
+ * <a onmouseover=\"
+ * (function(___OUTERS___) {
+ * ___OUTERS___.alert(1);
+ * })(___.getOuters(" + ___.getId(___OUTERS___) + "))
+ * \">Mouse here</a>
+ * ";
+ * </pre>
+ * If this is executed by a plugin whose outers is assigned id 42,
+ * it generates html with the same meaning as<pre>
+ * <a onmouseover="___.getOuters(42).alert(1)">Mouse here</a>
+ * </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<
+ * <a href="opensocial.Activity.MediaItem.html">MediaItem</a>></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<String, String></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.<Object>} 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]