Closed Bug 157624 Opened 22 years ago Closed 22 years ago

freeze nsISupportsPrimitives.idl

Categories

(Core :: XPCOM, defect, P2)

defect

Tracking

()

RESOLVED FIXED
mozilla1.2alpha

People

(Reporter: alecf, Assigned: alecf)

References

()

Details

(Whiteboard: fix in hand)

Attachments

(2 files, 5 obsolete files)

from bug 157047, I realized that we are freezing interfaces that eventually use
nsISupportsWString (via nsISimpleEnumerator) and other similar interfaces... we
need to freeze them. 

In the process, we really need to change nsISupportsWString and
nsISupportsString to use the new string types, as this structure is more often
used to enumerate strings, and is thus called in a loop.
dbradley, objections?
Blocks: 157137
ok, dmose pointed out some odd stuff, and we came to this conclusion:
right now, the mappings go more or less like:
"String" -> "char*"
"WString" -> "PRunichar*"

I think we should drop the old string primitives, and just use nsA*String&
types, such that
"String" -> "nsAString&"
"CString" -> "nsACString&"

Mostly because the "w" in "wstring" holds meaning in IDL, but aside from these
primitives, the "W" in nsISupportsWString gives us no added value in C++.
dbradley, how does this effect the xpconnect?
Oh.  Wow.  I did not realize this was still unfrozen...

Whatever changes we make, we should, imo, fix one issue with the current
interface.  Given an nsISupportsW?String, you can get a pointer to the data but
_not_ how much data there is!  This forces people to pass the lengths around in
odd ways...
i'm travelling today and will need a few days to catch up from my weekend vacation. can people give me time to check this idl file before they freeze? I know that I have made at least one change to it or its relatives.
Whiteboard: please-waitfor:timeless
Alec, did you mean AString and CString?

As far as the change to nsISupports[W]String that shouldn't be a problem.
Probably have to change the test that uses it, but I don't see anything else in
XPConnect that references it.

As far as freezing nsISupportsPrimitives.idl, does freezing this as a file mean
no new interfaces or that the existing interfaces won't change?
no, I meant what I typed - my argument against putting the "A" in the interface
name is that the interface is meant as a refcounted wrapper for a string object,
in the abstract sense, not a wrapper for the specific C++ type "nsAString" 

dmose and I went around a few times on this already, and more or less agreed to
disagree :)
there's a comment about nsIAllocator. Afaik it needs to be corrected to
nsIMemory. but that's another alecf project :)
Whiteboard: please-waitfor:timeless
ok, I'll take this over - I've got one mammoth patch to do the first thing I
described (rename nsISupportsString->nsISupportsCString and
nsISupportsWString->nsISupportsString) - and no I'm not that fast, I just know
some perl tricks :)
Assignee: dougt → alecf
This patch changes the interface names as I just described, as well as fixing
CIDs, CONTRACTIDs, and concrete class names. Can I get a review?
I'd like to land this first, and then change the API itself.
(and yeah, I'll have a commercial tree patch as well)
Comment on attachment 92914 [details] [diff] [review]
change interface names

I should get a prize for best nit :)
xpctest_primitives.js (both files) had a nicely structured table where the
commas lined up, please fix :)
Comment on attachment 92914 [details] [diff] [review]
change interface names

r=dougt.  what timeless said.
Attachment #92914 - Flags: review+
heh. yeah yeah, I fixed up that table real nice-like. :)
Comment on attachment 92914 [details] [diff] [review]
change interface names

got a sr=jag in person
Attachment #92914 - Flags: superreview+
Status: NEW → ASSIGNED
Priority: -- → P2
Target Milestone: --- → mozilla1.2alpha
one thing I mentioned in person to jag is that we might also want a
nsISupportsUTF8String at some point. But that's a different bug.
So does freezing this mean we'll not be able to add more types?
nah, I would hope not. Either than or we just keep adding
nsISupportsPrimitives2, etc. But I think the primary point of freezing is to
freeze forward - so that new apps that #include "nsISupportsPrimitives.h" don't
break with future versions.
i thought the idea of a frozen interface was that it couldn't change at all
(except for comments, and only for clarification, not for meaning).

As such, i'd suggest freezing all of the interfaces in the file
*except* interface nsISupportsPrimitive which of course doesn't actually work
because everything derives from it glory.

Well can we freeze it with const unsigned short 18..max unsigned short as
unusedSlot18..unusedSlotMax

That way when we need to add another primitive, we are merely renaming a string,
which would of course break jscompat. oh well. forget it. I'll expect to see
nsISupportsPrimitive2 before the year is out.
ok, the first patch has landed. Now to actually make the harder (i.e. not quite
mechanical) change of switching wstring->AString and string->ACString
good news here - I was able to eliminate
setDataWithLength/adoptData/adoptDataWithLength completely, so that the
string-supports objects remain as simple as the other objects. Patch
forthcoming, after I figure out what files I actually changed :)
Attached patch switch to new string classes (obsolete) — Splinter Review
ok, this cleans up nsISupportsString/nsISupportsCString and switches us over to
the new string classes. Reviews? Its pretty straightforward. It includes the
removal of nsI
Comment on attachment 94233 [details] [diff] [review]
switch to new string classes

>Index: mozilla/directory/c-sdk/config/Makefile
>-topsrcdir	= ..
>-srcdir		= .
>+topsrcdir	= /cygdrive/c/alecf/string/mozilla/directory/c-sdk
>+srcdir		= /cygdrive/c/alecf/string/mozilla/directory/c-sdk/config
>+VPATH		= /cygdrive/c/alecf/string/mozilla/directory/c-sdk/config
you really don't want to do this. (applies to a bunch of c-sdk Makefiles) blame
dmose?


>Index: mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
>===================================================================
>RCS file: /cvsroot/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp,v
>retrieving revision 1.60
>diff -u -r1.60 nsWindowWatcher.cpp
>--- mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp	6 Aug 2002 00:51:57 -0000	1.60
>+++ mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp	6 Aug 2002 20:26:13 -0000
>@@ -1740,11 +1740,11 @@
>       nsCOMPtr<nsISupportsCString> p(do_QueryInterface(argPrimitive));
>       NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
> 
>-      char *data;
>+      nsCAutoString data;
> 
>-      p->GetData(&data);
>+      p->GetData(data);
> 
>-      JSString *str = ::JS_NewString(cx, data, strlen(data));
>+      JSString *str = ::JS_NewString(cx, ToNewCString(data), data.Length());
>       NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);

1391 /*
1392  * Strings.
1393  *
1394  * NB: JS_NewString takes ownership of bytes on success, avoiding a copy;
but
1395  * on error (signified by null return), it leaves bytes owned by the
caller.
1396  * So the caller must free bytes in the error case, if it has no use for
them.
1397  * In contrast, all the JS_New*StringCopy* functions do not take ownership
of
1398  * the character memory passed to them -- they copy it.
1399  */
1400 extern JS_PUBLIC_API(JSString *)
1401 JS_NewString(JSContext *cx, char *bytes, size_t length);

you leak ToNewCString on failure :-)

note that this happens at leasta  few times.


>+NS_IMETHODIMP
>+nsPrefLocalizedString::GetData(PRUnichar** _retval)
>+{
>+  nsAutoString data;
...
>+  return NS_OK;
>+}
>+
>+NS_IMETHODIMP
>+nsPrefLocalizedString::SetData(const PRUnichar *aData)
>+{
>+    return SetData(nsDependentString(aData));
> }
trivial nit, be consistent about 2/4 space indentation =)

Index: mozilla/widget/src/xpwidgets/nsPrimitiveHelpers.cpp
>@@ -108,13 +112,19 @@
> 
>   if ( strcmp(aFlavor,kTextMime) == 0 ) {
>     nsCOMPtr<nsISupportsCString> plainText ( do_QueryInterface(aPrimitive) );
>-    if ( plainText )
>-      plainText->GetData ( NS_REINTERPRET_CAST(char**, aDataBuff) );
>+    if ( plainText ) {
>+      nsCAutoString data;
>+      plainText->GetData ( data );
>+      *aDataBuff = NS_REINTERPRET_CAST(char*, ToNewCString(data));
>+    }
>   }
the reinterpret cast appears useless here ^v
>   else {
>     nsCOMPtr<nsISupportsString> doubleByteText ( do_QueryInterface(aPrimitive) );
>-    if ( doubleByteText )
>-      doubleByteText->GetData ( NS_REINTERPRET_CAST(PRUnichar**, aDataBuff) );
>+    if ( doubleByteText ) {
>+      nsAutoString data;
>+      doubleByteText->GetData ( data );
>+      *aDataBuff = NS_REINTERPRET_CAST(PRUnichar*, ToNewCString(data));
>+    }
>   }
> 
> }

>Index: mozilla/mailnews/import/src/nsImportAddressBooks.cpp
>@@ -543,32 +543,16 @@
> 
> void nsImportGenericAddressBooks::SetLogs( nsString& success, nsString& error, nsISupportsString *pSuccess, nsISupportsString *pError)
> {
>-	nsString	str;
>-	PRUnichar *	pStr = nsnull;
>+	nsAutoString str = nsnull;
> 	if (pSuccess) {
>-		pSuccess->GetData( &pStr);
>-		if (pStr) {
>-			str = pStr;
>-			nsCRT::free( pStr);
>-			pStr = nsnull;
>-			str.Append( success);
>-			pSuccess->SetData( str.get());
>-		}
>-		else {
>-			pSuccess->SetData( success.get());			
>-		}
>+		pSuccess->GetData(str);
>+        str.Append(success);
>+        pSuccess->SetData( success);
i know that it was there before, but the space after the paren bothers me :-(
^v
> 	}
> 	if (pError) {
>-		pError->GetData( &pStr);
>-		if (pStr) {
>-			str = pStr;
>-			nsCRT::free( pStr);
>-			str.Append( error);
>-			pError->SetData( str.get());
>-		}
>-		else {
>-			pError->SetData( error.get());			
>-		}
>+		pError->GetData(str);
>+        str.Append(error);
>+        pError->SetData( error);
> 	}	
> }
> 

this file suffers from tabs (hrm, actually, so did the previous one...):
>Index: mozilla/mailnews/import/src/nsImportMail.cpp
so... the comment in mozilla/xpcom/ds/nsSupportsPrimitives.h makes it sound like
|setDataWithLength|, |adoptData|, |adoptDataWithLength| are exposed, whereas in
reality they are not...  setDataWithLength is no loss, but the adopt* functions
could be useful as [noscript] functions in the idl so that C++ callers could use
them,,,
ok, it was worth updating for that odd leak-on-failure, so I did due diligence
on the rest of the review - except the tabs. I'm just not going to fix tabs
this time around. (and I left out those wacky Makefile changes)

as for bz's comment regarding adopt: while I agree that the adopt* functions
"could be useful" I think we've shyed away from Adopt() style mechanisms,
because we don't know how the string was allocated (and thus the proper way to
free it as well) - so I certainly wouldn't keep it in a frozen interface.

And since:
1) nobody uses the mechanism now
2) these objects aren't holding very large buffers

I think its not worth providing the Adopt() "just in case" - it will be more
headaches and there has been no obvious demand for it in the 2-3 years that
this interface has existed.
Attachment #94233 - Attachment is obsolete: true
nsWindowWatcher.cpp:

+      char *dataBytes = ToNewCString(data);
+      JSString *str = ::JS_NewString(cx, dataBytes, data.Length());

Shouldn't you return NS_ERROR_OUT_OF_MEMORY if dataBytes is null?

Same in the wide char version of this code.

I got about a third of the way through and that's all I found, so far.  ;)
ok, let's all agree that I just added that in my tree.. good catch!
I noticed there were a number of calls to ToString() where GetData() could now
be used to save us an allocation - so this patch includes that conversion.

again, reviews anyone?
Attachment #94256 - Attachment is obsolete: true
Comment on attachment 94331 [details] [diff] [review]
switch to new string classes v1.1

r=dougt
Attachment #94331 - Flags: review+
Comment on attachment 94331 [details] [diff] [review]
switch to new string classes v1.1

>Index: mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
>===================================================================
>RCS file: /cvsroot/mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp,v
>retrieving revision 1.60
>diff -u -r1.60 nsWindowWatcher.cpp
>--- mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp	6 Aug 2002 00:51:57 -0000	1.60
>+++ mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp	7 Aug 2002 16:04:27 -0000
>@@ -1740,11 +1740,22 @@
>       nsCOMPtr<nsISupportsCString> p(do_QueryInterface(argPrimitive));
>       NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
> 
>-      char *data;
>+      nsCAutoString data;
> 
>-      p->GetData(&data);
>+      p->GetData(data);
>+
>+      // JS_NewString takes ownership, but we have to free on error,
>+      // so we need to keep the raw pointer around
>+      char *dataBytes = ToNewCString(data);
>+      if (!dataBytes)
>+        return NS_ERROR_OUT_OF_MEMORY;
>+      
>+      JSString *str = ::JS_NewString(cx, dataBytes, data.Length());

Why not use JS_NewStringCopyN?

>+      if (!str) {
>+        nsMemory::Free(dataBytes);
>+        return NS_ERROR_OUT_OF_MEMORY;
>+      }
> 
>-      JSString *str = ::JS_NewString(cx, data, strlen(data));
>       NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);

This NS_ENSURE_TRUE is redundant with the above check, but if you use CopyN you
can get rid of the above check instead.

>@@ -1755,15 +1766,25 @@
>       nsCOMPtr<nsISupportsString> p(do_QueryInterface(argPrimitive));
>       NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
> 
>-      PRUnichar *data;
>+      nsAutoString data;
> 
>-      p->GetData(&data);
>+      p->GetData(data);
> 
>+      // JS_NewUCString takes ownership, but we have to free on error,
>+      // so we need to keep the raw pointer around
>+      PRUnichar *dataBytes = ToNewUnicode(data);
>+      if (!dataBytes)
>+        return NS_ERROR_OUT_OF_MEMORY;
>+      
>       // cast is probably safe since wchar_t and jschar are expected
>       // to be equivalent; both unsigned 16-bit entities
>-      JSString *str = ::JS_NewUCString(cx, NS_REINTERPRET_CAST(jschar *, data),
>-                          nsCRT::strlen(data));
>-      NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
>+      JSString *str = ::JS_NewUCString(cx,
>+                                       NS_REINTERPRET_CAST(jschar *,dataBytes),
>+                                       data.Length());
>+      if (!str) {
>+        nsMemory::Free(dataBytes);
>+        return NS_ERROR_OUT_OF_MEMORY;
>+      }

Same applies.

>Index: mozilla/netwerk/base/src/nsIOService.cpp
>===================================================================
>RCS file: /cvsroot/mozilla/netwerk/base/src/nsIOService.cpp,v
>retrieving revision 1.147
>diff -u -r1.147 nsIOService.cpp
>--- mozilla/netwerk/base/src/nsIOService.cpp	6 Aug 2002 00:52:42 -0000	1.147
>+++ mozilla/netwerk/base/src/nsIOService.cpp	7 Aug 2002 16:04:27 -0000
>@@ -517,13 +517,13 @@
>         if (NS_FAILED(rv)) break;
> 
>         // get the entry string
>-        nsXPIDLCString entryString;
>-        rv = entry->GetData(getter_Copies(entryString));
>+        nsCAutoString entryString;
>+        rv = entry->GetData(entryString);
>         if (NS_FAILED(rv)) break;
> 
>-        if (strcmp(entryString, scheme) == 0) {
>+        if (entryString.Equals(scheme) == 0) {

This is not what you want.

Can you get another r= on this patch and e-mail me when you think it's ready
for sr=?
Attachment #94331 - Flags: needs-work+
To clarify, I haven't looked at the rest of this patch.
sorry, I don't know the JS API - I'll try using JS_NewStringCopyN and fix the
other stuff...
Nothing to be sorry for, alecf, just pointing it out so you can improve your
patch (and hopefully future ones). As for the |.Equals(...) == 0| thing, it's
unfortunate you missed that, dougt, but it's good that it was caught. I'll take
a look at the rest of this patch when I get bored again of being on vacation
;-), in the mean time, I'd appreciate it if you (both) could take another look
at this patch and catch any other oversights.
ok, this has been cleaned up - and I found one other typo in the os2 widget
code that I've cleaned up... but I think this patch is now ready... using
JS_NewStringCopyN etc...
Attachment #94331 - Attachment is obsolete: true
Comment on attachment 95141 [details] [diff] [review]
switch to new string classes v1.2

This is just the part for nsBookmarksService.cpp
Attachment #95141 - Flags: needs-work+
argh! Sorry jag, I don't know how that happened.
Take two, and asking again.. can I get reviews here?
Attachment #95141 - Attachment is obsolete: true
ok, some questions about the API change...

 interface nsISupportsCString : nsISupportsPrimitive
 {
+    attribute ACString data;
     string toString();
-
-    /**
-     * Note: setting |data| and using |setDataWithLength| make a copy of
-     * the data string argument. Using |adoptData| and |adoptDataWithLength|,
-     * which are not scriptable, subsumes the data string as the internal
-     * buffer.
-     *
-     * Also note that the |length| param should not include space for a null
-     * terminator, nor should it account for the size of a char. It should
-     * only be the number of characters for which there is space in the string.
-     */
-
-    void setDataWithLength(in unsigned long length,
-                           [size_is(length)] in string data);
-
-    [noscript] void adoptData(in charPtr data);
-
-    [noscript] void adoptDataWithLength(in unsigned long length,
-                                        [size_is(length)] in charPtr data);
 };

why don't we want toString() to return ACString?  just too much work to fix all
the callsites?  also, why don't we want to keep the adopt methods?  nsCString
supports Adopt, so wouldn't these be trivial to provide?  same thing goes for
nsISupportsString.
I didn't change toString() because I as I recall, xpconnect doesn't do automatic
conversion to strings in JS without it.

This might be remedied easily by just fixing XPConnect.. but since I've updated
all the c++ callsites to use GetData(), I'd like to handle the toString() in
another patch.

see comment 24 for my "Why no adopt?" answer.. The short answer is, nobody uses
it and it opens up funky ownership/allocator issues that I don't think should
cloud this interface.
Whiteboard: fix in hand
oh, i didn't realize XPCONNECT did something special with toString()...
interesting.  in that case, it might be nice to document the fact that
toString() exists for that purpose.

i'm fine with leaving the Adopt methods off since they aren't used, and we could
always achieve the same thing using sharable strings.  however, i don't really
like the argument that Adopt is bad because of mixed allocator problems...
that's why we have nsMemory::Alloc isn't it?  afterall, we have the identical
problem when some foreign component implements an interface with a |string| or
|wstring| getter.
darin: cool. I agree, the allocator argument is a little weak :)

Hey, can I get a review from you?
dougt is on vacation right now...
Comment on attachment 95970 [details] [diff] [review]
switch to new string classes v1.2 again

>Index: mozilla/embedding/components/windowwatcher/src/nsWindowWatcher.cpp

>+      JSString *str = ::JS_NewStringCopyN(cx, data.get(), data.Length());

too bad there isn't a way for a nsCString to yield ownership of its buffer :(


>Index: mozilla/js/src/xpconnect/src/xpccomponents.cpp

>+                        JSString* idstr = JS_NewStringCopyZ(cx, name.get());

nit: use JS_NewStringCopyN to eliminate a call to strlen


>Index: mozilla/modules/libpref/src/nsPref.cpp

>+    if (NS_FAILED(rv))
>+      return rv;
>+    
>+    nsAutoString data;
>+    rv = theString->GetData(data);
>+    if (NS_FAILED(rv))
>+      return rv;
>+
>+    *_retval = ToNewUnicode(data);
>+    if (!*_retval)
>+      return NS_ERROR_OUT_OF_MEMORY;

how about using ToString() here to avoid the extra buffer copy?  this
same pattern repeats.


>Index: mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp

>+        str->SetData(nsDependentCString(APPLICATION_GZIP,
>+                                        sizeof(APPLICATION_GZIP) - 1));

how about using NS_LITERAL_CSTRING instead?  this same pattern
repeats.


i stopped here:

>Index: mozilla/xpcom/ds/nsSupportsPrimitives.cpp
darin: ok nits fixed.. I was thinking I wasn't going to be able to do
NS_LITERAL_CSTRING because of the whole macros issue with prepending an "L" onto
the macro name - but looking at your comment I'm realizing its not a wide
string. duh!

do you mind finishing the review so that I don't have to keep attaching patches,
asking people to review them AGAIN, and so forth? As you can see I've been a few
rounds with this patch already :)
no problem, i only stopped halfway through because i ran out of time ;-)
...hoping to resume sometime today.
Comment on attachment 95970 [details] [diff] [review]
switch to new string classes v1.2 again

>Index: mozilla/xpcom/ds/nsSupportsPrimitives.cpp

>+NS_IMETHODIMP nsSupportsCStringImpl::GetData(nsACString& aData)
>+    if (mData)
>+        aData = nsDependentCString(mData, mLength);
>     else
>+        aData.Truncate(0);
>+    return NS_OK;

nit: why not make mData be a nsCString?  it seems like that would
greatly simplify the implementation of this class.  you could do
away with a lot of the code... especially in the SetData case.
there doesn't seem to be any advantage to storing a raw pointer and
length.


>Index: mozilla/mailnews/import/src/nsImportAddressBooks.cpp

>+	nsAutoString str;
> 	if (pSuccess) {
>+		pSuccess->GetData(str);
>+        str.Append(success);
>+        pSuccess->SetData(success);
> 	}
> 	if (pError) {
>+		pError->GetData(str);
>+        str.Append(error);
>+        pError->SetData(error);
> 	}	

nit: fix indentation


>Index: mozilla/mailnews/import/src/nsImportMail.cpp

>+	nsAutoString str;
> 	if (pSuccess) {
>+		pSuccess->GetData(str);
>+        str.Append(success);
>+        pSuccess->SetData(str);
> 	}
> 	if (pError) {
>+		pError->GetData(str);
>+        str.Append(error);
>+        pError->SetData(str);
> 	}	

nit: fix indentation

otherwise, the patch looks good.
argh. the indentation in that file is because the import stuff uses tabs. I'll
try to re-indent the lines around those that I changed.

Yeah, I guess I was debating what made sense there.. I think that this was
originally made when nsCString was a 20+ byte structure, so maybe people were
optimizing for space, I don't know. These days its just 12 bytes (4 more bytes
than  mLength and mData combined) so I'll just switch us over.
ah, no I see the original purpose - it was to support AdoptData(), because this
pre-dated Adopt() in strings. in any case, I'm dropping it so this is going to
get signifigantly simpler.
ok, addressing all of darin's comments....
as for indenting in nsImportMail.cpp - I correctly indented every line I
touched, but the whole file is a confusion of tabs and spaces - using either
wouldn't make the patch look right. At least it has a correct emacs header so
that the tabs are correctly expanded to 4 spaces.

Can I get final reviews? thanks folks.
Attachment #95970 - Attachment is obsolete: true
Comment on attachment 96347 [details] [diff] [review]
switch to new string classes v1.21

r/sr=darin
Attachment #96347 - Flags: superreview+
Comment on attachment 95141 [details] [diff] [review]
switch to new string classes v1.2

r=dougt
Attachment #95141 - Flags: review+
Comment on attachment 96347 [details] [diff] [review]
switch to new string classes v1.21

re-applying the has-review flag
Attachment #96347 - Flags: review+
If we're using nsCString for mData, we had better explicitly comment that .get()
should never be called on it...

Even as it is, I'm not completely sure that nsCString always does the right
thing if the data has embedded nulls in it (and nsISupportsCString should
certainly support embedded nulls).
yeah, nsCString supports embedded nulls fine, as far as I know. This was a big
thing that gessner used to brag about when the string classes first arrived.

in any case, nsSupportsCString does not do anything with the data itself, it
just copies it to/from the internal string object.
ok, interfaces have been marked "under_review" so that we can document them
further and see if there's anything else we need.
looks like doug got the last of the @status FROZEN in another bug. Marking fixed.
Status: ASSIGNED → RESOLVED
Closed: 22 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.