Bug 1225603. Codegen ToJSValue overloads for Web IDL enums. r=smaug,jib

This commit is contained in:
Boris Zbarsky 2015-11-21 12:15:11 -05:00
parent 7341ea4227
commit dbc94a4932
6 changed files with 125 additions and 33 deletions

View File

@ -6267,21 +6267,14 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
resultLoc = result
conversion = fill(
"""
{
// Scope for resultStr
MOZ_ASSERT(uint32_t(${result}) < ArrayLength(${strings}));
JSString* resultStr = JS_NewStringCopyN(cx, ${strings}[uint32_t(${result})].value, ${strings}[uint32_t(${result})].length);
if (!resultStr) {
$*{exceptionCode}
}
$*{setResultStr}
if (!ToJSValue(cx, ${result}, $${jsvalHandle})) {
$*{exceptionCode}
}
$*{successCode}
""",
result=resultLoc,
strings=(type.unroll().inner.identifier.name + "Values::" +
ENUM_ENTRY_VARIABLE_NAME),
exceptionCode=exceptionCode,
setResultStr=setString("resultStr"))
successCode=successCode)
if type.nullable():
conversion = CGIfElseWrapper(
@ -9054,11 +9047,53 @@ def getEnumValueName(value):
' rename our internal EndGuard_ to something else')
return nativeName
class CGEnumToJSValue(CGAbstractMethod):
def __init__(self, enum):
enumType = enum.identifier.name
self.stringsArray = enumType + "Values::" + ENUM_ENTRY_VARIABLE_NAME
CGAbstractMethod.__init__(self, None, "ToJSValue", "bool",
[Argument("JSContext*", "aCx"),
Argument(enumType, "aArgument"),
Argument("JS::MutableHandle<JS::Value>",
"aValue")])
def definition_body(self):
return fill(
"""
MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(${strings}));
JSString* resultStr =
JS_NewStringCopyN(aCx, ${strings}[uint32_t(aArgument)].value,
${strings}[uint32_t(aArgument)].length);
if (!resultStr) {
return false;
}
aValue.setString(resultStr);
return true;
""",
strings=self.stringsArray)
class CGEnum(CGThing):
def __init__(self, enum):
CGThing.__init__(self)
self.enum = enum
strings = CGNamespace(
self.stringsNamespace(),
CGGeneric(declare=("extern const EnumEntry %s[%d];\n" %
(ENUM_ENTRY_VARIABLE_NAME, self.nEnumStrings())),
define=fill(
"""
extern const EnumEntry ${name}[${count}] = {
$*{entries}
{ nullptr, 0 }
};
""",
name=ENUM_ENTRY_VARIABLE_NAME,
count=self.nEnumStrings(),
entries=''.join('{"%s", %d},\n' % (val, len(val))
for val in self.enum.values()))))
toJSValue = CGEnumToJSValue(enum)
self.cgThings = CGList([strings, toJSValue], "\n")
def stringsNamespace(self):
return self.enum.identifier.name + "Values"
@ -9079,22 +9114,10 @@ class CGEnum(CGThing):
strings = CGNamespace(self.stringsNamespace(),
CGGeneric(declare="extern const EnumEntry %s[%d];\n"
% (ENUM_ENTRY_VARIABLE_NAME, self.nEnumStrings())))
return decl + "\n" + strings.declare()
return decl + "\n" + self.cgThings.declare()
def define(self):
strings = fill(
"""
extern const EnumEntry ${name}[${count}] = {
$*{entries}
{ nullptr, 0 }
};
""",
name=ENUM_ENTRY_VARIABLE_NAME,
count=self.nEnumStrings(),
entries=''.join('{"%s", %d},\n' % (val, len(val))
for val in self.enum.values()))
return CGNamespace(self.stringsNamespace(),
CGGeneric(define=indent(strings))).define()
return self.cgThings.define()
def deps(self):
return self.enum.getDeps()
@ -12997,6 +13020,11 @@ class CGBindingRoot(CGThing):
bindingHeaders["mozilla/dom/DOMJSClass.h"] = descriptors
bindingHeaders["mozilla/dom/ScriptSettings.h"] = dictionaries # AutoJSAPI
bindingHeaders["xpcpublic.h"] = dictionaries # xpc::UnprivilegedJunkScope
# Ensure we see our enums in the generated .cpp file, for the ToJSValue
# method body. Also ensure that we see jsapi.h.
if enums:
bindingHeaders[CGHeaders.getDeclarationFilename(enums[0])] = True
bindingHeaders["jsapi.h"] = True
# For things that have [UseCounter]
def descriptorRequiresTelemetry(desc):

View File

@ -723,10 +723,7 @@ public:
RefPtr<Promise> promise = mProxy->WorkerPromise();
if (NS_SUCCEEDED(mStatus)) {
MOZ_ASSERT(uint32_t(mState) < ArrayLength(PushPermissionStateValues::strings));
nsAutoCString stringState(PushPermissionStateValues::strings[uint32_t(mState)].value,
PushPermissionStateValues::strings[uint32_t(mState)].length);
promise->MaybeResolve(NS_ConvertUTF8toUTF16(stringState));
promise->MaybeResolve(mState);
} else {
promise->MaybeReject(aCx, JS::UndefinedHandleValue);
}

View File

@ -12,7 +12,9 @@ for var in ('MOZILLA_EXTERNAL_LINKAGE', 'USE_FAKE_MEDIA_STREAMS', 'USE_FAKE_PCOB
DEFINES[var] = True
LOCAL_INCLUDES += [
'!/dom/bindings',
'!/dist/include/mozilla/dom', # Binding headers (because binding
# implementations include them).
'!/dom/bindings', # Binding implementations (urk).
'/dom/media/',
'/ipc/chromium/src',
'/media/mtransport',

View File

@ -40,7 +40,9 @@
#include "logging.h"
#include "stunserver.h"
#include "stunserver.cpp"
#ifdef SIGNALING_UNITTEST_STANDALONE
#include "PeerConnectionImplEnumsBinding.cpp"
#endif
#include "ice_ctx.h"
#include "ice_peer_ctx.h"
@ -340,6 +342,44 @@ TestObserver::NotifyDataChannel(nsIDOMDataChannel *channel, ER&)
return NS_OK;
}
static const char* PCImplSignalingStateStrings[] = {
"SignalingInvalid",
"SignalingStable",
"SignalingHaveLocalOffer",
"SignalingHaveRemoteOffer",
"SignalingHaveLocalPranswer",
"SignalingHaveRemotePranswer",
"SignalingClosed"
};
static const char* PCImplIceConnectionStateStrings[] = {
"new",
"checking",
"connected",
"completed",
"failed",
"disconnected",
"closed"
};
static const char* PCImplIceGatheringStateStrings[] = {
"new",
"gathering",
"complete"
};
#ifdef SIGNALING_UNITTEST_STANDALONE
static_assert(ArrayLength(PCImplSignalingStateStrings) ==
size_t(PCImplSignalingState::EndGuard_),
"Table sizes must match");
static_assert(ArrayLength(PCImplIceConnectionStateStrings) ==
size_t(PCImplIceConnectionState::EndGuard_),
"Table sizes must match");
static_assert(ArrayLength(PCImplIceGatheringStateStrings) ==
size_t(PCImplIceGatheringState::EndGuard_),
"Table sizes must match");
#endif // SIGNALING_UNITTEST_STANDALONE
NS_IMETHODIMP
TestObserver::OnStateChange(PCObserverStateType state_type, ER&, void*)
{
@ -357,7 +397,7 @@ TestObserver::OnStateChange(PCObserverStateType state_type, ER&, void*)
rv = pc->IceConnectionState(&gotice);
NS_ENSURE_SUCCESS(rv, rv);
std::cout << "ICE Connection State: "
<< PCImplIceConnectionStateValues::strings[int(gotice)].value
<< PCImplIceConnectionStateStrings[int(gotice)]
<< std::endl;
break;
case PCObserverStateType::IceGatheringState:
@ -366,7 +406,7 @@ TestObserver::OnStateChange(PCObserverStateType state_type, ER&, void*)
NS_ENSURE_SUCCESS(rv, rv);
std::cout
<< "ICE Gathering State: "
<< PCImplIceGatheringStateValues::strings[int(goticegathering)].value
<< PCImplIceGatheringStateStrings[int(goticegathering)]
<< std::endl;
break;
case PCObserverStateType::SdpState:
@ -378,7 +418,7 @@ TestObserver::OnStateChange(PCObserverStateType state_type, ER&, void*)
rv = pc->SignalingState(&gotsignaling);
NS_ENSURE_SUCCESS(rv, rv);
std::cout << "Signaling State: "
<< PCImplSignalingStateValues::strings[int(gotsignaling)].value
<< PCImplSignalingStateStrings[int(gotsignaling)]
<< std::endl;
break;
default:
@ -4712,6 +4752,19 @@ static int gtest_main(int argc, char **argv) {
return result;
}
#ifdef SIGNALING_UNITTEST_STANDALONE
static void verifyStringTable(const EnumEntry* bindingTable,
const char** ourTable)
{
while (bindingTable->value) {
if (strcmp(bindingTable->value, *ourTable)) {
MOZ_CRASH("Our tables are out of sync with the bindings");
}
++bindingTable;
++ourTable;
}
}
#endif // SIGNALING_UNITTEST_STANDALONE
int main(int argc, char **argv) {
@ -4726,6 +4779,16 @@ int main(int argc, char **argv) {
calleeName = ansiMagenta + calleeName + ansiColorOff;
}
#ifdef SIGNALING_UNITTEST_STANDALONE
// Verify our string tables are correct.
verifyStringTable(PCImplSignalingStateValues::strings,
test::PCImplSignalingStateStrings);
verifyStringTable(PCImplIceConnectionStateValues::strings,
test::PCImplIceConnectionStateStrings);
verifyStringTable(PCImplIceGatheringStateValues::strings,
test::PCImplIceGatheringStateStrings);
#endif // SIGNALING_UNITTEST_STANDALONE
std::string tmp = get_environment("STUN_SERVER_ADDRESS");
if (tmp != "")
g_stun_server_address = tmp;

View File

@ -39,6 +39,7 @@ LOCAL_INCLUDES += [
USE_LIBS += [
'/media/webrtc/signalingstandalone/signaling_ecc/ecc',
'fallible',
'js', # Turns out, binding implementations use JS, who knew.
'media_standalone',
'mfbt',
'mozglue',

View File

@ -2,4 +2,5 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#define SIGNALING_UNITTEST_STANDALONE 1
#include "../signaling_unittests.cpp"