Improve output: distinguish between failed assertions (failures) and unexpected exceptions (errors), and print a filtered stack trace for any exception.

This commit is contained in:
jeb228 2010-01-29 22:13:57 +00:00
commit 4f2e303079
1839 changed files with 235630 additions and 0 deletions

View file

@ -0,0 +1,214 @@
/*
Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
modified BSD license. For more information on Dojo licensing, see:
http://dojotoolkit.org/community/licensing.shtml
*/
/**
An implementation of Flash 8's ExternalInterface that works with Flash 6
and which is source-compatible with Flash 8.
@author Brad Neuberg, bkn3@columbia.edu
*/
class DojoExternalInterface{
public static var available:Boolean;
public static var dojoPath = "";
public static var _fscommandReady = false;
public static var _callbacks = new Array();
public static function initialize(){
//getURL("javascript:dojo.debug('FLASH:DojoExternalInterface initialize')");
// FIXME: Set available variable by testing for capabilities
DojoExternalInterface.available = true;
// extract the dojo base path
DojoExternalInterface.dojoPath = DojoExternalInterface.getDojoPath();
//getURL("javascript:dojo.debug('FLASH:dojoPath="+DojoExternalInterface.dojoPath+"')");
// Sometimes, on IE, the fscommand infrastructure can take a few hundred
// milliseconds the first time a page loads. Set a timer to keep checking
// to make sure we can issue fscommands; otherwise, our calls to fscommand
// for setCallback() and loaded() will just "disappear"
_root.fscommandReady = false;
var fsChecker = function(){
// issue a test fscommand
fscommand("fscommandReady");
// JavaScript should set _root.fscommandReady if it got the call
if(_root.fscommandReady == "true"){
DojoExternalInterface._fscommandReady = true;
clearInterval(_root.fsTimer);
}
};
_root.fsTimer = setInterval(fsChecker, 100);
}
public static function addCallback(methodName:String, instance:Object,
method:Function) : Boolean{
// A variable that indicates whether the call below succeeded
_root._succeeded = null;
// Callbacks are registered with the JavaScript side as follows.
// On the Flash side, we maintain a lookup table that associates
// the methodName with the actual instance and method that are
// associated with this method.
// Using fscommand, we send over the action "addCallback", with the
// argument being the methodName to add, such as "foobar".
// The JavaScript takes these values and registers the existence of
// this callback point.
// precede the method name with a _ character in case it starts
// with a number
_callbacks["_" + methodName] = {_instance: instance, _method: method};
_callbacks[_callbacks.length] = methodName;
// The API for ExternalInterface says we have to make sure the call
// succeeded; check to see if there is a value
// for _succeeded, which is set by the JavaScript side
if(_root._succeeded == null){
return false;
}else{
return true;
}
}
public static function call(methodName:String,
resultsCallback:Function) : Void{
// FIXME: support full JSON serialization
// First, we pack up all of the arguments to this call and set them
// as Flash variables, which the JavaScript side will unpack using
// plugin.GetVariable(). We set the number of arguments as "_numArgs",
// and add each argument as a variable, such as "_1", "_2", etc., starting
// from 0.
// We then execute an fscommand with the action "call" and the
// argument being the method name. JavaScript takes the method name,
// retrieves the arguments using GetVariable, executes the method,
// and then places the return result in a Flash variable
// named "_returnResult".
_root._numArgs = arguments.length - 2;
for(var i = 2; i < arguments.length; i++){
var argIndex = i - 2;
_root["_" + argIndex] = arguments[i];
}
_root._returnResult = undefined;
fscommand("call", methodName);
// immediately return if the caller is not waiting for return results
if(resultsCallback == undefined || resultsCallback == null){
return;
}
// check at regular intervals for return results
var resultsChecker = function(){
if(_root._returnResult != undefined){
clearInterval(_root._callbackID);
resultsCallback.call(null, _root._returnResult);
}
};
_root._callbackID = setInterval(resultsChecker, 100);
}
/**
Called by Flash to indicate to JavaScript that we are ready to have
our Flash functions called. Calling loaded()
will fire the dojo.flash.loaded() event, so that JavaScript can know that
Flash has finished loading and adding its callbacks, and can begin to
interact with the Flash file.
*/
public static function loaded(){
//getURL("javascript:dojo.debug('FLASH:loaded')");
// one more step: see if fscommands are ready to be executed; if not,
// set an interval that will keep running until fscommands are ready;
// make sure the gateway is loaded as well
var execLoaded = function(){
if(DojoExternalInterface._fscommandReady == true){
clearInterval(_root.loadedInterval);
// initialize the small Flash file that helps gateway JS to Flash
// calls
DojoExternalInterface._initializeFlashRunner();
}
};
if(_fscommandReady == true){
execLoaded();
}else{
_root.loadedInterval = setInterval(execLoaded, 50);
}
}
/**
Handles and executes a JavaScript to Flash method call. Used by
initializeFlashRunner.
*/
public static function _handleJSCall(){
// get our parameters
var numArgs = parseInt(_root._numArgs);
var jsArgs = new Array();
for(var i = 0; i < numArgs; i++){
var currentValue = _root["_" + i];
jsArgs.push(currentValue);
}
// get our function name
var functionName = _root._functionName;
// now get the actual instance and method object to execute on,
// using our lookup table that was constructed by calls to
// addCallback on initialization
var instance = _callbacks["_" + functionName]._instance;
var method = _callbacks["_" + functionName]._method;
// execute it
var results = method.apply(instance, jsArgs);
// return the results
_root._returnResult = results;
}
/** Called by the flash6_gateway.swf to indicate that it is loaded. */
public static function _gatewayReady(){
for(var i = 0; i < _callbacks.length; i++){
fscommand("addCallback", _callbacks[i]);
}
call("dojo.flash.loaded");
}
/**
When JavaScript wants to communicate with Flash it simply sets
the Flash variable "_execute" to true; this method creates the
internal Movie Clip, called the Flash Runner, that makes this
magic happen.
*/
public static function _initializeFlashRunner(){
// figure out where our Flash movie is
var swfLoc = DojoExternalInterface.dojoPath + "flash6_gateway.swf";
// load our gateway helper file
_root.createEmptyMovieClip("_flashRunner", 5000);
_root._flashRunner._lockroot = true;
_root._flashRunner.loadMovie(swfLoc);
}
private static function getDojoPath(){
var url = _root._url;
var start = url.indexOf("baseRelativePath=") + "baseRelativePath=".length;
var path = url.substring(start);
var end = path.indexOf("&");
if(end != -1){
path = path.substring(0, end);
}
return path;
}
}
// vim:ts=4:noet:tw=0:

Binary file not shown.

View file

@ -0,0 +1,234 @@
/*
Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
modified BSD license. For more information on Dojo licensing, see:
http://dojotoolkit.org/community/licensing.shtml
*/
/**
A wrapper around Flash 8's ExternalInterface; DojoExternalInterface is needed so that we
can do a Flash 6 implementation of ExternalInterface, and be able
to support having a single codebase that uses DojoExternalInterface
across Flash versions rather than having two seperate source bases,
where one uses ExternalInterface and the other uses DojoExternalInterface.
DojoExternalInterface class does a variety of optimizations to bypass ExternalInterface's
unbelievably bad performance so that we can have good performance
on Safari; see the blog post
http://codinginparadise.org/weblog/2006/02/how-to-speed-up-flash-8s.html
for details.
@author Brad Neuberg, bkn3@columbia.edu
*/
import flash.external.ExternalInterface;
class DojoExternalInterface{
public static var available:Boolean;
public static var dojoPath = "";
private static var flashMethods:Array = new Array();
private static var numArgs:Number;
private static var argData:Array;
private static var resultData = null;
public static function initialize(){
// extract the dojo base path
DojoExternalInterface.dojoPath = DojoExternalInterface.getDojoPath();
// see if we need to do an express install
var install:ExpressInstall = new ExpressInstall();
if(install.needsUpdate){
install.init();
}
// register our callback functions
ExternalInterface.addCallback("startExec", DojoExternalInterface, startExec);
ExternalInterface.addCallback("setNumberArguments", DojoExternalInterface,
setNumberArguments);
ExternalInterface.addCallback("chunkArgumentData", DojoExternalInterface,
chunkArgumentData);
ExternalInterface.addCallback("exec", DojoExternalInterface, exec);
ExternalInterface.addCallback("getReturnLength", DojoExternalInterface,
getReturnLength);
ExternalInterface.addCallback("chunkReturnData", DojoExternalInterface,
chunkReturnData);
ExternalInterface.addCallback("endExec", DojoExternalInterface, endExec);
// set whether communication is available
DojoExternalInterface.available = ExternalInterface.available;
DojoExternalInterface.call("loaded");
}
public static function addCallback(methodName:String, instance:Object,
method:Function) : Boolean{
// register DojoExternalInterface methodName with it's instance
DojoExternalInterface.flashMethods[methodName] = instance;
// tell JavaScript about DojoExternalInterface new method so we can create a proxy
ExternalInterface.call("dojo.flash.comm._addExternalInterfaceCallback",
methodName);
return true;
}
public static function call(methodName:String,
resultsCallback:Function) : Void{
// we might have any number of optional arguments, so we have to
// pass them in dynamically; strip out the results callback
var parameters = new Array();
for(var i = 0; i < arguments.length; i++){
if(i != 1){ // skip the callback
parameters.push(arguments[i]);
}
}
var results = ExternalInterface.call.apply(ExternalInterface, parameters);
// immediately give the results back, since ExternalInterface is
// synchronous
if(resultsCallback != null && typeof resultsCallback != "undefined"){
resultsCallback.call(null, results);
}
}
/**
Called by Flash to indicate to JavaScript that we are ready to have
our Flash functions called. Calling loaded()
will fire the dojo.flash.loaded() event, so that JavaScript can know that
Flash has finished loading and adding its callbacks, and can begin to
interact with the Flash file.
*/
public static function loaded(){
DojoExternalInterface.call("dojo.flash.loaded");
}
public static function startExec():Void{
DojoExternalInterface.numArgs = null;
DojoExternalInterface.argData = null;
DojoExternalInterface.resultData = null;
}
public static function setNumberArguments(numArgs):Void{
DojoExternalInterface.numArgs = numArgs;
DojoExternalInterface.argData = new Array(DojoExternalInterface.numArgs);
}
public static function chunkArgumentData(value, argIndex:Number):Void{
//getURL("javascript:dojo.debug('FLASH: chunkArgumentData, value="+value+", argIndex="+argIndex+"')");
var currentValue = DojoExternalInterface.argData[argIndex];
if(currentValue == null || typeof currentValue == "undefined"){
DojoExternalInterface.argData[argIndex] = value;
}else{
DojoExternalInterface.argData[argIndex] += value;
}
}
public static function exec(methodName):Void{
// decode all of the arguments that were passed in
for(var i = 0; i < DojoExternalInterface.argData.length; i++){
DojoExternalInterface.argData[i] =
DojoExternalInterface.decodeData(DojoExternalInterface.argData[i]);
}
var instance = DojoExternalInterface.flashMethods[methodName];
DojoExternalInterface.resultData = instance[methodName].apply(
instance, DojoExternalInterface.argData);
// encode the result data
DojoExternalInterface.resultData =
DojoExternalInterface.encodeData(DojoExternalInterface.resultData);
//getURL("javascript:dojo.debug('FLASH: encoded result data="+DojoExternalInterface.resultData+"')");
}
public static function getReturnLength():Number{
if(DojoExternalInterface.resultData == null ||
typeof DojoExternalInterface.resultData == "undefined"){
return 0;
}
var segments = Math.ceil(DojoExternalInterface.resultData.length / 1024);
return segments;
}
public static function chunkReturnData(segment:Number):String{
var numSegments = DojoExternalInterface.getReturnLength();
var startCut = segment * 1024;
var endCut = segment * 1024 + 1024;
if(segment == (numSegments - 1)){
endCut = segment * 1024 + DojoExternalInterface.resultData.length;
}
var piece = DojoExternalInterface.resultData.substring(startCut, endCut);
//getURL("javascript:dojo.debug('FLASH: chunking return piece="+piece+"')");
return piece;
}
public static function endExec():Void{
}
private static function decodeData(data):String{
// we have to use custom encodings for certain characters when passing
// them over; for example, passing a backslash over as //// from JavaScript
// to Flash doesn't work
data = DojoExternalInterface.replaceStr(data, "&custom_backslash;", "\\");
data = DojoExternalInterface.replaceStr(data, "\\\'", "\'");
data = DojoExternalInterface.replaceStr(data, "\\\"", "\"");
return data;
}
private static function encodeData(data){
//getURL("javascript:dojo.debug('inside flash, data before="+data+"')");
// double encode all entity values, or they will be mis-decoded
// by Flash when returned
data = DojoExternalInterface.replaceStr(data, "&", "&amp;");
// certain XMLish characters break Flash's wire serialization for
// ExternalInterface; encode these into a custom encoding, rather than
// the standard entity encoding, because otherwise we won't be able to
// differentiate between our own encoding and any entity characters
// that are being used in the string itself
data = DojoExternalInterface.replaceStr(data, '<', '&custom_lt;');
data = DojoExternalInterface.replaceStr(data, '>', '&custom_gt;');
// encode control characters and JavaScript delimiters
data = DojoExternalInterface.replaceStr(data, "\n", "\\n");
data = DojoExternalInterface.replaceStr(data, "\r", "\\r");
data = DojoExternalInterface.replaceStr(data, "\f", "\\f");
data = DojoExternalInterface.replaceStr(data, "'", "\\'");
data = DojoExternalInterface.replaceStr(data, '"', '\"');
//getURL("javascript:dojo.debug('inside flash, data after="+data+"')");
return data;
}
/**
Flash ActionScript has no String.replace method or support for
Regular Expressions! We roll our own very simple one.
*/
private static function replaceStr(inputStr:String, replaceThis:String,
withThis:String):String {
var splitStr = inputStr.split(replaceThis)
inputStr = splitStr.join(withThis)
return inputStr;
}
private static function getDojoPath(){
var url = _root._url;
var start = url.indexOf("baseRelativePath=") + "baseRelativePath=".length;
var path = url.substring(start);
var end = path.indexOf("&");
if(end != -1){
path = path.substring(0, end);
}
return path;
}
}
// vim:ts=4:noet:tw=0:

View file

@ -0,0 +1,81 @@
/*
Copyright (c) 2004-2006, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
modified BSD license. For more information on Dojo licensing, see:
http://dojotoolkit.org/community/licensing.shtml
*/
/**
* Based on the expressinstall.as class created by Geoff Stearns as part
* of the FlashObject library.
*
* Use this file to invoke the Macromedia Flash Player Express Install functionality
* This file is intended for use with the FlashObject embed script. You can download FlashObject
* and this file at the following URL: http://blog.deconcept.com/flashobject/
*
* Usage:
* var ExpressInstall = new ExpressInstall();
*
* // test to see if install is needed:
* if (ExpressInstall.needsUpdate) { // returns true if update is needed
* ExpressInstall.init(); // starts the update
* }
*
* NOTE: Your Flash movie must be at least 214px by 137px in order to use ExpressInstall.
*
*/
class ExpressInstall {
public var needsUpdate:Boolean;
private var updater:MovieClip;
private var hold:MovieClip;
public function ExpressInstall(){
// does the user need to update?
this.needsUpdate = (_root.MMplayerType == undefined) ? false : true;
}
public function init():Void{
this.loadUpdater();
}
public function loadUpdater():Void {
System.security.allowDomain("fpdownload.macromedia.com");
// hope that nothing is at a depth of 10000000, you can change this depth if needed, but you want
// it to be on top of your content if you have any stuff on the first frame
this.updater = _root.createEmptyMovieClip("expressInstallHolder", 10000000);
// register the callback so we know if they cancel or there is an error
var _self = this;
this.updater.installStatus = _self.onInstallStatus;
this.hold = this.updater.createEmptyMovieClip("hold", 1);
// can't use movieClipLoader because it has to work in 6.0.65
this.updater.onEnterFrame = function():Void {
if(typeof this.hold.startUpdate == 'function'){
_self.initUpdater();
this.onEnterFrame = null;
}
}
var cacheBuster:Number = Math.random();
this.hold.loadMovie("http://fpdownload.macromedia.com/pub/flashplayer/"
+"update/current/swf/autoUpdater.swf?"+ cacheBuster);
}
private function initUpdater():Void{
this.hold.redirectURL = _root.MMredirectURL;
this.hold.MMplayerType = _root.MMplayerType;
this.hold.MMdoctitle = _root.MMdoctitle;
this.hold.startUpdate();
}
public function onInstallStatus(msg):Void{
getURL("javascript:dojo.flash.install._onInstallStatus('"+msg+"')");
}
}