mirror of
https://github.com/samba-team/samba.git
synced 2025-12-13 16:23:50 +03:00
274 lines
7.2 KiB
C
274 lines
7.2 KiB
C
/*
|
|
* @file ejsClass.c
|
|
* @brief EJS class support
|
|
*/
|
|
/********************************* Copyright **********************************/
|
|
/*
|
|
* @copy default
|
|
*
|
|
* Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
|
|
* Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved.
|
|
*
|
|
* This software is distributed under commercial and open source licenses.
|
|
* You may use the GPL open source license described below or you may acquire
|
|
* a commercial license from Mbedthis Software. You agree to be fully bound
|
|
* by the terms of either license. Consult the LICENSE.TXT distributed with
|
|
* this software for full details.
|
|
*
|
|
* This software is open source; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version. See the GNU General Public License for more
|
|
* details at: http://www.mbedthis.com/downloads/gplLicense.html
|
|
*
|
|
* This program is distributed WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* This GPL license does NOT permit incorporating this software into
|
|
* proprietary programs. If you are unable to comply with the GPL, you must
|
|
* acquire a commercial license to use this software. Commercial licenses
|
|
* for this software and support services are available from Mbedthis
|
|
* Software at http://www.mbedthis.com
|
|
*
|
|
* @end
|
|
*/
|
|
/********************************* Includes ***********************************/
|
|
|
|
#include "ejs.h"
|
|
|
|
#if BLD_FEATURE_EJS
|
|
|
|
/************************************ Code ************************************/
|
|
/*
|
|
* Internal API
|
|
*
|
|
* Routine to create a simple class object. This routine will create a
|
|
* stand-alone class object. Callers must insert this into the relevant
|
|
* "global" object for name resolution. From these class objects, instance
|
|
* objects may be created via the javascript "new" command.
|
|
*
|
|
* Users should use ejsDefineClass
|
|
*/
|
|
|
|
EjsVar *ejsCreateSimpleClass(Ejs *ep, EjsVar *baseClass, const char *className)
|
|
{
|
|
EjsProperty *pp;
|
|
EjsVar *classObj;
|
|
|
|
/*
|
|
* Create an instance of an Object to act as the static class object
|
|
*/
|
|
classObj = ejsCreateSimpleObjUsingClass(ep, baseClass);
|
|
if (classObj == 0) {
|
|
mprAssert(classObj);
|
|
return 0;
|
|
}
|
|
ejsSetClassName(ep, classObj, className);
|
|
|
|
/*
|
|
* Set the propotype property to point to this class.
|
|
* Note: this is a self reference so the alive bit will not be turned on.
|
|
*/
|
|
pp = ejsSetProperty(ep, classObj, "prototype", classObj);
|
|
ejsMakePropertyEnumerable(pp, 0);
|
|
|
|
return classObj;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Define a class in the given interpreter. If parentClass is specified, the
|
|
* class is defined in the parent. Otherwise, the class will be defined
|
|
* locally/globally. ClassName and extends are full variable specs
|
|
* (may contain ".")
|
|
*/
|
|
|
|
EjsVar *ejsDefineClass(Ejs *ep, const char *className, const char *extends,
|
|
EjsCMethod constructor)
|
|
{
|
|
EjsVar *parentClass, *classObj, *baseClass, *vp;
|
|
char *name;
|
|
char *cp;
|
|
|
|
/*
|
|
* If the className is a qualified name (with "."), then get the
|
|
* parent class name.
|
|
*/
|
|
name = mprStrdup(ep, className);
|
|
cp = strrchr(name, '.');
|
|
if (cp != 0) {
|
|
*cp++ = '\0';
|
|
className = cp;
|
|
parentClass = ejsFindProperty(ep, 0, 0, ep->global, ep->local, name, 0);
|
|
if (parentClass == 0 || parentClass->type != EJS_TYPE_OBJECT) {
|
|
mprError(ep, MPR_LOC, "Can't find class's parent class %s", name);
|
|
mprFree(name);
|
|
return 0;
|
|
}
|
|
|
|
} else {
|
|
/*
|
|
* Simple class name without a "." so create the class locally
|
|
* if a local scope exists, otherwise globally.
|
|
*/
|
|
parentClass = (ep->local) ? ep->local : ep->global;
|
|
}
|
|
|
|
if (parentClass == 0) {
|
|
mprError(ep, MPR_LOC, "Can't find parent class");
|
|
mprFree(name);
|
|
return 0;
|
|
}
|
|
|
|
/* OPT should use function that doesn't parse [] . */
|
|
baseClass = ejsGetClass(ep, 0, extends);
|
|
if (baseClass == 0) {
|
|
mprAssert(baseClass);
|
|
mprFree(name);
|
|
return 0;
|
|
}
|
|
|
|
classObj = ejsCreateSimpleClass(ep, baseClass, className);
|
|
if (classObj == 0) {
|
|
mprAssert(classObj);
|
|
mprFree(name);
|
|
return 0;
|
|
}
|
|
|
|
if (constructor) {
|
|
ejsDefineCMethod(ep, classObj, className, constructor, 0);
|
|
}
|
|
|
|
ejsSetPropertyAndFree(ep, parentClass, className, classObj);
|
|
|
|
vp = ejsGetPropertyAsVar(ep, parentClass, className);
|
|
mprFree(name);
|
|
|
|
return vp;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Find a class and return the property defining the class. ClassName may
|
|
* contain "." and is interpreted relative to obj. Obj is typically some
|
|
* parent object, ep->local or ep->global. If obj is null, then the global
|
|
* space is used.
|
|
*/
|
|
|
|
EjsVar *ejsGetClass(Ejs *ep, EjsVar *obj, const char *className)
|
|
{
|
|
EjsVar *vp;
|
|
|
|
mprAssert(ep);
|
|
|
|
/*
|
|
* Search first for a constructor of the name of class
|
|
* global may not be defined yet.
|
|
*/
|
|
if (obj) {
|
|
vp = ejsFindProperty(ep, 0, 0, obj, 0, className, 0);
|
|
|
|
} else {
|
|
mprAssert(ep->global);
|
|
vp = ejsFindProperty(ep, 0, 0, ep->global, ep->local, className, 0);
|
|
}
|
|
if (vp == 0 || vp->type != EJS_TYPE_OBJECT) {
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Return a reference to the prototype (self) reference. This
|
|
* ensures that even if "obj" is deleted, this reference will remain
|
|
* usable.
|
|
*/
|
|
return ejsGetPropertyAsVar(ep, vp, "prototype");
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Return the class name of a class or object
|
|
*/
|
|
|
|
const char *ejsGetClassName(EjsVar *vp)
|
|
{
|
|
EjsObj *obj;
|
|
|
|
mprAssert(vp);
|
|
mprAssert(vp->type == EJS_TYPE_OBJECT);
|
|
mprAssert(vp->objectState->baseClass);
|
|
|
|
if (vp == 0 || !ejsVarIsObject(vp)) {
|
|
return 0;
|
|
}
|
|
obj = vp->objectState;
|
|
|
|
return obj->className;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/*
|
|
* Return the class name of an objects underlying class
|
|
* If called on an object, it returns the base class.
|
|
* If called on a class, it returns the base class for the class.
|
|
*/
|
|
|
|
const char *ejsGetBaseClassName(EjsVar *vp)
|
|
{
|
|
EjsObj *obj;
|
|
|
|
mprAssert(vp);
|
|
mprAssert(vp->type == EJS_TYPE_OBJECT);
|
|
mprAssert(vp->objectState->baseClass);
|
|
|
|
if (vp == 0 || !ejsVarIsObject(vp)) {
|
|
return 0;
|
|
}
|
|
obj = vp->objectState;
|
|
if (obj->baseClass == 0) {
|
|
return 0;
|
|
}
|
|
mprAssert(obj->baseClass->objectState);
|
|
|
|
return obj->baseClass->objectState->className;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
EjsVar *ejsGetBaseClass(EjsVar *vp)
|
|
{
|
|
if (vp == 0 || !ejsVarIsObject(vp) || vp->objectState == 0) {
|
|
mprAssert(0);
|
|
return 0;
|
|
}
|
|
return vp->objectState->baseClass;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
void ejsSetBaseClass(EjsVar *vp, EjsVar *baseClass)
|
|
{
|
|
if (vp == 0 || !ejsVarIsObject(vp) || vp->objectState == 0) {
|
|
mprAssert(0);
|
|
return;
|
|
}
|
|
vp->objectState->baseClass = baseClass;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
#else
|
|
void ejsProcsDummy() {}
|
|
|
|
/******************************************************************************/
|
|
#endif /* BLD_FEATURE_EJS */
|
|
|
|
/*
|
|
* Local variables:
|
|
* tab-width: 4
|
|
* c-basic-offset: 4
|
|
* End:
|
|
* vim:tw=78
|
|
* vim600: sw=4 ts=4 fdm=marker
|
|
* vim<600: sw=4 ts=4
|
|
*/
|