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,312 @@
/*
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
*/
dojo.provide("dojo.widget.Parse");
dojo.require("dojo.widget.Manager");
dojo.require("dojo.dom");
dojo.widget.Parse = function(fragment) {
this.propertySetsList = [];
this.fragment = fragment;
this.createComponents = function(frag, parentComp){
var comps = [ ];
var built = false;
// if we have items to parse/create at this level, do it!
try{
if((frag)&&(frag["tagName"])&&(frag!=frag["nodeRef"])){
var djTags = dojo.widget.tags;
// we split so that you can declare multiple
// non-destructive widgets from the same ctor node
var tna = String(frag["tagName"]).split(";");
for(var x=0; x<tna.length; x++){
var ltn = (tna[x].replace(/^\s+|\s+$/g, "")).toLowerCase();
if(djTags[ltn]){
built = true;
frag.tagName = ltn;
var ret = djTags[ltn](frag, this, parentComp, frag["index"]);
comps.push(ret);
}else{
if((dojo.lang.isString(ltn))&&(ltn.substr(0, 5)=="dojo:")){
dojo.debug("no tag handler registed for type: ", ltn);
}
}
}
}
}catch(e){
dojo.debug("dojo.widget.Parse: error:", e);
// throw(e);
// IE is such a bitch sometimes
}
// if there's a sub-frag, build widgets from that too
if(!built){
comps = comps.concat(this.createSubComponents(frag, parentComp));
}
return comps;
}
/* createSubComponents recurses over a raw JavaScript object structure,
and calls the corresponding handler for its normalized tagName if it exists
*/
this.createSubComponents = function(fragment, parentComp){
var frag, comps = [];
for(var item in fragment){
frag = fragment[item];
if ((frag)&&(typeof frag == "object")&&(frag!=fragment.nodeRef)&&(frag!=fragment["tagName"])){
comps = comps.concat(this.createComponents(frag, parentComp));
}
}
return comps;
}
/* parsePropertySets checks the top level of a raw JavaScript object
structure for any propertySets. It stores an array of references to
propertySets that it finds.
*/
this.parsePropertySets = function(fragment) {
return [];
var propertySets = [];
for(var item in fragment){
if( (fragment[item]["tagName"] == "dojo:propertyset") ) {
propertySets.push(fragment[item]);
}
}
// FIXME: should we store these propertySets somewhere for later retrieval
this.propertySetsList.push(propertySets);
return propertySets;
}
/* parseProperties checks a raw JavaScript object structure for
properties, and returns an array of properties that it finds.
*/
this.parseProperties = function(fragment) {
var properties = {};
for(var item in fragment){
// FIXME: need to check for undefined?
// case: its a tagName or nodeRef
if((fragment[item] == fragment["tagName"])||
(fragment[item] == fragment.nodeRef)){
// do nothing
}else{
if((fragment[item]["tagName"])&&
(dojo.widget.tags[fragment[item].tagName.toLowerCase()])){
// TODO: it isn't a property or property set, it's a fragment,
// so do something else
// FIXME: needs to be a better/stricter check
// TODO: handle xlink:href for external property sets
}else if((fragment[item][0])&&(fragment[item][0].value!="")&&(fragment[item][0].value!=null)){
try{
// FIXME: need to allow more than one provider
if(item.toLowerCase() == "dataprovider") {
var _this = this;
this.getDataProvider(_this, fragment[item][0].value);
properties.dataProvider = this.dataProvider;
}
properties[item] = fragment[item][0].value;
var nestedProperties = this.parseProperties(fragment[item]);
// FIXME: this kind of copying is expensive and inefficient!
for(var property in nestedProperties){
properties[property] = nestedProperties[property];
}
}catch(e){ dojo.debug(e); }
}
}
}
return properties;
}
/* getPropertySetById returns the propertySet that matches the provided id
*/
this.getDataProvider = function(objRef, dataUrl) {
// FIXME: this is currently sync. To make this async, we made need to move
//this step into the widget ctor, so that it is loaded when it is needed
// to populate the widget
dojo.io.bind({
url: dataUrl,
load: function(type, evaldObj){
if(type=="load"){
objRef.dataProvider = evaldObj;
}
},
mimetype: "text/javascript",
sync: true
});
}
this.getPropertySetById = function(propertySetId){
for(var x = 0; x < this.propertySetsList.length; x++){
if(propertySetId == this.propertySetsList[x]["id"][0].value){
return this.propertySetsList[x];
}
}
return "";
}
/* getPropertySetsByType returns the propertySet(s) that match(es) the
* provided componentClass
*/
this.getPropertySetsByType = function(componentType){
var propertySets = [];
for(var x=0; x < this.propertySetsList.length; x++){
var cpl = this.propertySetsList[x];
var cpcc = cpl["componentClass"]||cpl["componentType"]||null;
// FIXME: propertySetId is not in scope here
if((cpcc)&&(propertySetId == cpcc[0].value)){
propertySets.push(cpl);
}
}
return propertySets;
}
/* getPropertySets returns the propertySet for a given component fragment
*/
this.getPropertySets = function(fragment){
var ppl = "dojo:propertyproviderlist";
var propertySets = [];
var tagname = fragment["tagName"];
if(fragment[ppl]){
var propertyProviderIds = fragment[ppl].value.split(" ");
// FIXME: should the propertyProviderList attribute contain #
// syntax for reference to ids or not?
// FIXME: need a better test to see if this is local or external
// FIXME: doesn't handle nested propertySets, or propertySets that
// just contain information about css documents, etc.
for(var propertySetId in propertyProviderIds){
if((propertySetId.indexOf("..")==-1)&&(propertySetId.indexOf("://")==-1)){
// get a reference to a propertySet within the current parsed structure
var propertySet = this.getPropertySetById(propertySetId);
if(propertySet != ""){
propertySets.push(propertySet);
}
}else{
// FIXME: add code to parse and return a propertySet from
// another document
// alex: is this even necessaray? Do we care? If so, why?
}
}
}
// we put the typed ones first so that the parsed ones override when
// iteration happens.
return (this.getPropertySetsByType(tagname)).concat(propertySets);
}
/*
nodeRef is the node to be replaced... in the future, we might want to add
an alternative way to specify an insertion point
componentName is the expected dojo widget name, i.e. Button of ContextMenu
properties is an object of name value pairs
*/
this.createComponentFromScript = function(nodeRef, componentName, properties){
var ltn = "dojo:" + componentName.toLowerCase();
if(dojo.widget.tags[ltn]){
properties.fastMixIn = true;
return [dojo.widget.tags[ltn](properties, this, null, null, properties)];
}else{
if(ltn.substr(0, 5)=="dojo:"){
dojo.debug("no tag handler registed for type: ", ltn);
}
}
}
}
dojo.widget._parser_collection = {"dojo": new dojo.widget.Parse() };
dojo.widget.getParser = function(name){
if(!name){ name = "dojo"; }
if(!this._parser_collection[name]){
this._parser_collection[name] = new dojo.widget.Parse();
}
return this._parser_collection[name];
}
/**
* Creates widget.
*
* @param name The name of the widget to create
* @param props Key-Value pairs of properties of the widget
* @param refNode If the last argument is specified this node is used as
* a reference for inserting this node into a DOM tree else
* it beomces the domNode
* @param position The position to insert this widget's node relative to the
* refNode argument
* @return The new Widget object
*/
dojo.widget.createWidget = function(name, props, refNode, position){
var lowerCaseName = name.toLowerCase();
var namespacedName = "dojo:" + lowerCaseName;
var isNode = ( dojo.byId(name) && (!dojo.widget.tags[namespacedName]) );
// if we got a node or an unambiguious ID, build a widget out of it
if( (arguments.length==1) && ((typeof name != "string")||(isNode)) ){
// we got a DOM node
var xp = new dojo.xml.Parse();
// FIXME: we should try to find the parent!
var tn = (isNode) ? dojo.byId(name) : name;
return dojo.widget.getParser().createComponents(xp.parseElement(tn, null, true))[0];
}
function fromScript (placeKeeperNode, name, props) {
props[namespacedName] = {
dojotype: [{value: lowerCaseName}],
nodeRef: placeKeeperNode,
fastMixIn: true
};
return dojo.widget.getParser().createComponentFromScript(
placeKeeperNode, name, props, true);
}
if (typeof name != "string" && typeof props == "string") {
dojo.deprecated("dojo.widget.createWidget",
"argument order is now of the form " +
"dojo.widget.createWidget(NAME, [PROPERTIES, [REFERENCENODE, [POSITION]]])", "0.4");
return fromScript(name, props, refNode);
}
props = props||{};
var notRef = false;
var tn = null;
var h = dojo.render.html.capable;
if(h){
tn = document.createElement("span");
}
if(!refNode){
notRef = true;
refNode = tn;
if(h){
document.body.appendChild(refNode);
}
}else if(position){
dojo.dom.insertAtPosition(tn, refNode, position);
}else{ // otherwise don't replace, but build in-place
tn = refNode;
}
var widgetArray = fromScript(tn, name, props);
if (!widgetArray || !widgetArray[0] || typeof widgetArray[0].widgetType == "undefined") {
throw new Error("createWidget: Creation of \"" + name + "\" widget failed.");
}
if (notRef) {
if (widgetArray[0].domNode.parentNode) {
widgetArray[0].domNode.parentNode.removeChild(widgetArray[0].domNode);
}
}
return widgetArray[0]; // just return the widget
}
dojo.widget.fromScript = function(name, props, refNode, position){
dojo.deprecated("dojo.widget.fromScript", " use " +
"dojo.widget.createWidget instead", "0.4");
return dojo.widget.createWidget(name, props, refNode, position);
}