/*
* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
// INCLUDE FILES
#include "kjs_console.h"
#include "kjs/Lookup.h"
#include "Chrome.h"
#include "PlatformString.h"
#include "kjs/context.h"
#include "kjs/nodes.h"
//#include "flogger.h"
// EXTERNAL DATA STRUCTURES
// EXTERNAL FUNCTION PROTOTYPES
// CONSTANTS
const TInt KFormattedMaxLength=0x200;
// MACROS
// LOCAL CONSTANTS AND MACROS
// MODULE DATA STRUCTURES
// LOCAL FUNCTION PROTOTYPES
// FORWARD DECLARATIONS
using namespace KJS;
using namespace WebCore;
const ClassInfo ConsoleObject::info = { "ConsoleObject", 0, &ConsoleTable, 0 };
// ============================= LOCAL FUNCTIONS ===============================
/*
@begin ConsoleTable 7
error ConsoleObject::error DontDelete|Function 1
info ConsoleObject::information DontDelete|Function 1
warn ConsoleObject::warn DontDelete|Function 1
log ConsoleObject::log DontDelete|Function 1
debug ConsoleObject::debug DontDelete|Function 1
assert ConsoleObject::assert DontDelete|Function 1
lineno ConsoleObject::lineno DontDelete|ReadOnly
sourceURL ConsoleObject::sourceURL DontDelete|ReadOnly
@end
*/
// ============================ MEMBER FUNCTIONS ===============================
// ----------------------------------------------------------------------------
// ConsoleObject::toString
// Returns string representation of the object
//
//
// ----------------------------------------------------------------------------
UString ConsoleObject::toString(ExecState *exec) const
{
return "[object ConsoleObject]";
}
// ----------------------------------------------------------------------------
// ConsoleObject::getValueProperty
//
//
// ----------------------------------------------------------------------------
JSValue* ConsoleObject::getValueProperty(ExecState *exec, int token) const
{
switch( token )
{
case error:
case information:
case warn:
case log:
case debug:
case assert:
{
ConsoleFunc *cf = new ConsoleFunc( exec,token );
return cf;
}
default:
return throwError(exec, GeneralError);
}
return jsUndefined();
}
// ----------------------------------------------------------------------------
// ConsoleObject::getOwnPropertySlot
//
//
//
// ----------------------------------------------------------------------------
bool ConsoleObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
const HashEntry* entry = Lookup::findEntry(&ConsoleTable, propertyName);
if (entry)
{
slot.setStaticEntry(this, entry, staticValueGetter<ConsoleObject>);
return true;
}
return JSObject::getOwnPropertySlot(exec, propertyName, slot);
}
// ----------------------------------------------------------------------------
// ConsoleFunc::formatMsg
// formats the arguments into a message according to the format string(first arg).
//
// ----------------------------------------------------------------------------
void ConsoleFunc::formatMsg(ExecState *exec, const List &args)
{
d->m_formattedMsg = String();
if (!args.size())
return;
bool validPattern = true; // is this valid pattern, i.e. %s, %x, %f, %i, %d, etc?
bool reachedMaxLen = false;
String KTruncateSign("...");
TInt lenReserved = 50;
TInt64 maxInteger = 0x100000000;
// retrieve the format string
ListIterator it = args.begin();
String formatStr((*it)->toString(exec));
it++;
bool endOfArgs = (it != args.end())? false: true;
// format the value according to the converters:
for (TInt index = formatStr.find('%', 0);
(index != KErrNotFound) && !reachedMaxLen;
index = formatStr.find('%',0))
{
// copy the buffer before next %
if (index + d->m_formattedMsg.length() > KFormattedMaxLength - lenReserved)
{
d->m_formattedMsg.append(formatStr.left(KFormattedMaxLength - d->m_formattedMsg.length() - KTruncateSign.length()));
d->m_formattedMsg.append(KTruncateSign);
reachedMaxLen = true;
break;
}
d->m_formattedMsg.append(formatStr.left(index));
UChar patternChar = formatStr[index +1];
JSValue* argValue = (*it);
switch (patternChar.unicode())
{
case 's':
case 'S':
// retrieve and copy string
if (!endOfArgs)
{
if (argValue->toString(exec).size() + d->m_formattedMsg.length() <= KFormattedMaxLength - lenReserved)
d->m_formattedMsg.append(argValue->toString(exec));
else
{
d->m_formattedMsg.append(String(argValue->toString(exec)).left(d->m_formattedMsg.length() - KTruncateSign.length()));
d->m_formattedMsg.append(KTruncateSign);
reachedMaxLen = true;
}
}
break;
case 'f':
case 'F':
// convert to float and
if (!endOfArgs)
{
if (argValue == jsNaN() || !argValue->isNumber())
d->m_formattedMsg.append(String("[not valid float]"));
else
d->m_formattedMsg.append(String::number(argValue->getNumber()));
}
break;
case 'i':
case 'd':
if (!endOfArgs)
{
if (argValue == jsNaN() || !argValue->isNumber())
d->m_formattedMsg.append(String("[not valid integer]"));
else
d->m_formattedMsg.append(String::number(static_cast<int32_t>(argValue->getNumber())));
}
break;
case 'u':
case 'x':
if (!endOfArgs)
{
uint32_t uintValue;
if(!argValue->getUInt32(uintValue))
d->m_formattedMsg.append(String("[not valid integer]"));
else
if (patternChar == 'x')
{
char hex[32];
snprintf(hex, 32, "%x", uintValue);
d->m_formattedMsg.append(hex);
}
else
d->m_formattedMsg.append(String::number(uintValue));
}
break;
case '%':
d->m_formattedMsg.append('%');
break;
default:
validPattern = false;
} // switch
if (!endOfArgs) ++it;
if (it == args.end())
endOfArgs = true;
int remainedLen;
if (validPattern)
remainedLen = formatStr.length() - index - 2;
else
remainedLen = formatStr.length() - index - 1;
formatStr = formatStr.right(remainedLen);
} // for
if (!reachedMaxLen && formatStr.length() + d->m_formattedMsg.length() <= KFormattedMaxLength)
{
d->m_formattedMsg.append(formatStr);
}
else if (!reachedMaxLen)
{
d->m_formattedMsg.append(formatStr.left(KFormattedMaxLength - d->m_formattedMsg.length() - KTruncateSign.length()));
d->m_formattedMsg.append(KTruncateSign);
}
}
// ----------------------------------------------------------------------------
// ConsoleFunc::ConsoleFunc
// Default constructor
//
//
// ----------------------------------------------------------------------------
ConsoleFunc::ConsoleFunc(ExecState* exec, int fType)
: JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()),
funcType(fType)
{
d = new ConsolePrivate;
d->m_url = String(exec->context()->currentBody()->sourceURL());
d->m_lineno = exec->context()->lineno(); // get the execution line no.
}
// ----------------------------------------------------------------------------
// ConsoleFunc::callAsFunction
// Calls this object as if it is a function
//
//
// ----------------------------------------------------------------------------
JSValue* ConsoleFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
{
//RFileLogger::Write(_L("Browser"), _L("console_debug.txt"), EFileLoggingModeAppend,
// _L("callAsFunction called"));
if (!thisObj->inherits(&ConsoleObject::info)) {
return throwError(exec, GeneralError);
}
if (d->m_lineno == -1)
d->m_lineno = exec->context()->currentBody()->lineNo();
ConsoleObject *console = static_cast<ConsoleObject *>(thisObj);
formatMsg(exec, args);
switch (funcType)
{
case ConsoleObject::error:
case ConsoleObject::information:
case ConsoleObject::warn:
case ConsoleObject::log:
console->m_chrome->addMessageToConsole(JSMessageSource,
(WebCore::MessageLevel)funcType, String(d->m_formattedMsg), d->m_lineno, String(d->m_url));
break;
case ConsoleObject::debug:
{
break;
}
case ConsoleObject::assert:
{
break;
}
default:
break;
}
return jsUndefined();
}
//END OF FILE