source: webkit/trunk/JavaScriptCore/API/JSClassRef.cpp@ 15497

Last change on this file since 15497 was 15497, checked in by ggaren, 19 years ago

Reviewed by Maciej.


  • Added automatic prototype creation for classes.


A class stores a weak reference to a prototype, which is cleared when
the prototype is garbage collected, to avoid a reference cycle.


We now have an attributes field in JSClassDefinition, that currently is
used only to override automatic prototype creation when you want to manage your
own prototypes, but can be extended in the future for other nefarious purposes.


Similarly, we have JSObjectMake and JSObjectMakeWithPrototype, the latter
allowing you to manage your own prototypes.


JSObjectMakeConstructor is more interesting now, able to make a constructor
on your behalf if you just give it a class.


  • Removed bogus old code from minidom.js.


  • Tweaked the headerdocs.


  • Added more GC testing, which caught some leaks, and tested more funny edge cases in lookup, which caught a lookup bug. Removed some testing we used to do with MyObject because it was redundant with the new, cool stuff.


While fixing the lookup bug I retracted this change:


"If a static setProperty callback returns 'false', to indicate that the
property was not set, we no longer forward the set request up the class
chain, because that's almost certainly not what the programmer expected."

Returning false when setting a static property is a little silly, but you can see
it being useful when shadowing a base class's static properties, and, regardless
of usefullness, this is the defined behavior of the setProperty callback.


  • Plus a little ASCII art, for the kids.
File size: 6.1 KB
Line 
1// -*- mode: c++; c-basic-offset: 4 -*-
2/*
3 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "APICast.h"
28#include "JSCallbackObject.h"
29#include "JSClassRef.h"
30#include "JSObjectRef.h"
31#include "identifier.h"
32
33using namespace KJS;
34
35const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
36
37OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* protoClass)
38 : refCount(0)
39 , className(definition->className)
40 , parentClass(definition->parentClass)
41 , prototypeClass(0)
42 , staticValues(0)
43 , staticFunctions(0)
44 , initialize(definition->initialize)
45 , finalize(definition->finalize)
46 , hasProperty(definition->hasProperty)
47 , getProperty(definition->getProperty)
48 , setProperty(definition->setProperty)
49 , deleteProperty(definition->deleteProperty)
50 , getPropertyNames(definition->getPropertyNames)
51 , callAsFunction(definition->callAsFunction)
52 , callAsConstructor(definition->callAsConstructor)
53 , hasInstance(definition->hasInstance)
54 , convertToType(definition->convertToType)
55{
56 if (JSStaticValue* staticValue = definition->staticValues) {
57 staticValues = new StaticValuesTable();
58 while (staticValue->name) {
59 staticValues->add(Identifier(staticValue->name).ustring().rep(),
60 new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes));
61 ++staticValue;
62 }
63 }
64
65 if (JSStaticFunction* staticFunction = definition->staticFunctions) {
66 staticFunctions = new StaticFunctionsTable();
67 while (staticFunction->name) {
68 staticFunctions->add(Identifier(staticFunction->name).ustring().rep(),
69 new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes));
70 ++staticFunction;
71 }
72 }
73
74 if (protoClass)
75 prototypeClass = JSClassRetain(protoClass);
76}
77
78OpaqueJSClass::~OpaqueJSClass()
79{
80 if (staticValues) {
81 deleteAllValues(*staticValues);
82 delete staticValues;
83 }
84
85 if (staticFunctions) {
86 deleteAllValues(*staticFunctions);
87 delete staticFunctions;
88 }
89
90 if (prototypeClass)
91 JSClassRelease(prototypeClass);
92}
93
94JSClassRef OpaqueJSClass::createNoPrototype(const JSClassDefinition* definition)
95{
96 return new OpaqueJSClass(definition, 0);
97}
98
99void clearReferenceToPrototype(JSObjectRef prototype)
100{
101 OpaqueJSClass* jsClass = static_cast<OpaqueJSClass*>(JSObjectGetPrivate(prototype));
102 ASSERT(jsClass);
103 jsClass->cachedPrototype = 0;
104}
105
106JSClassRef OpaqueJSClass::create(const JSClassDefinition* definition)
107{
108 if (JSStaticFunction* staticFunctions = definition->staticFunctions) {
109 // copy functions into a prototype class
110 JSClassDefinition protoDefinition = kJSClassDefinitionEmpty;
111 protoDefinition.staticFunctions = staticFunctions;
112 protoDefinition.finalize = clearReferenceToPrototype;
113 OpaqueJSClass* protoClass = new OpaqueJSClass(&protoDefinition, 0);
114
115 // remove functions from the original definition
116 JSClassDefinition objectDefinition = *definition;
117 objectDefinition.staticFunctions = 0;
118 return new OpaqueJSClass(&objectDefinition, protoClass);
119 }
120
121 return new OpaqueJSClass(definition, 0);
122}
123
124/*!
125// Doc here in case we make this public. (Hopefully we won't.)
126@function
127 @abstract Returns the prototype that will be used when constructing an object with a given class.
128 @param ctx The execution context to use.
129 @param jsClass A JSClass whose prototype you want to get.
130 @result The JSObject prototype that was automatically generated for jsClass, or NULL if no prototype was automatically generated. This is the prototype that will be used when constructing an object using jsClass.
131*/
132JSObject* OpaqueJSClass::prototype(JSContextRef ctx)
133{
134 /* Class (C++) and prototype (JS) inheritance are parallel, so:
135 * (C++) | (JS)
136 * ParentClass | ParentClassPrototype
137 * ^ | ^
138 * | | |
139 * DerivedClass | DerivedClassPrototype
140 */
141
142 if (!prototypeClass)
143 return 0;
144
145 ExecState* exec = toJS(ctx);
146
147 if (!cachedPrototype) {
148 // Recursive, but should be good enough for our purposes
149 JSObject* parentPrototype = 0;
150 if (parentClass)
151 parentPrototype = parentClass->prototype(ctx); // can be null
152 if (!parentPrototype)
153 parentPrototype = exec->dynamicInterpreter()->builtinObjectPrototype();
154 cachedPrototype = new JSCallbackObject(exec, prototypeClass, parentPrototype, this); // set ourself as the object's private data, so it can clear our reference on destruction
155 }
156 return cachedPrototype;
157}
Note: See TracBrowser for help on using the repository browser.