Skip to content

Commit

Permalink
Refactor JavaScript local exceptions (#2574)
Browse files Browse the repository at this point in the history
  • Loading branch information
pepone authored Jul 26, 2024
1 parent dc2e185 commit 806f28c
Show file tree
Hide file tree
Showing 48 changed files with 722 additions and 1,679 deletions.
2 changes: 1 addition & 1 deletion cpp/src/slice2js/Gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1748,7 +1748,7 @@ Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p)
_out << eb;

_out << sp;
_out << nl << "static get _id()";
_out << nl << "static get _ice_id()";
_out << sb;
_out << nl << "return \"" << p->scoped() << "\";";
_out << eb;
Expand Down
2 changes: 1 addition & 1 deletion js/src/Ice/Communicator.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import { CommunicatorDestroyedException } from "./LocalExceptions.js";
import { generateUUID } from "./UUID.js";
import { identityToString } from "./IdentityUtil.js";
import { identityToString } from "./IdentityToString.js";
import { Promise } from "./Promise.js";
import { Debug } from "./Debug.js";
import { ObjectPrx } from "./ObjectPrx.js";
Expand Down
119 changes: 82 additions & 37 deletions js/src/Ice/ConnectionI.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,16 @@

import { LocalException } from "./LocalException.js";
import {
IllegalMessageSizeException,
ObjectAdapterDeactivatedException,
CommunicatorDestroyedException,
CloseConnectionException,
ConnectionManuallyClosedException,
ConnectionAbortedException,
ConnectionClosedException,
ConnectTimeoutException,
ConnectionIdleException,
ConnectionLostException,
CloseTimeoutException,
SocketException,
FeatureNotSupportedException,
UnmarshalOutOfBoundsException,
BadMagicException,
ConnectionNotValidatedException,
UnknownMessageException,
UnknownException,
} from "./LocalExceptions.js";

Expand Down Expand Up @@ -116,9 +110,6 @@ export class ConnectionI {
this._initialized = false;
this._validated = false;

this._readProtocol = new ProtocolVersion();
this._readProtocolEncoding = new EncodingVersion();

this._asyncRequests = new HashMap(); // Map<int, OutgoingAsync>

this._exception = null;
Expand Down Expand Up @@ -212,10 +203,16 @@ export class ConnectionI {
const r = new AsyncResultBase(this._communicator, "close", this, null, null);

if (mode == ConnectionClose.Forcefully) {
this.setState(StateClosed, new ConnectionManuallyClosedException(false));
this.setState(
StateClosed,
new ConnectionAbortedException("The connection was aborted by the application.", true),
);
r.resolve();
} else if (mode == ConnectionClose.Gracefully) {
this.setState(StateClosing, new ConnectionManuallyClosedException(true));
this.setState(
StateClosing,
new ConnectionClosedException("The connection was closed gracefully by the application.", true),
);
r.resolve();
} else {
Debug.assert(mode == ConnectionClose.GracefullyWithWait);
Expand Down Expand Up @@ -243,7 +240,10 @@ export class ConnectionI {
// as well.
//
Timer.setImmediate(() => {
this.setState(StateClosing, new ConnectionManuallyClosedException(true));
this.setState(
StateClosing,
new ConnectionClosedException("Connection close gracefully by the application.", true),
);
this._closePromises.forEach(p => p.resolve());
this._closePromises = [];
});
Expand Down Expand Up @@ -555,20 +555,38 @@ export class ConnectionI {
magic2 !== Protocol.magic[2] ||
magic3 !== Protocol.magic[3]
) {
throw new BadMagicException("", new Uint8Array([magic0, magic1, magic2, magic3]));
throw new ProtocolException(
`Bad magic in message header: ${magic0.toString(16)} ${magic1.toString(16)} ${magic2.toString(16)} ${magic3.toString(16)}`,
);
}

this._readProtocol._read(this._readStream);
Protocol.checkSupportedProtocol(this._readProtocol);
const protocolVersion = new ProtocolVersion();
protocolVersion._read(this._readStream);
if (
protocolVersion.major != Protocol.currentProtocol.major ||
protocolVersion.minor != Protocol.currentProtocol.minor
) {
throw new MarshalException(
`Invalid protocol version in message header: ${protocolVersion.major}.${protocolVersion.minor}`,
);
}

this._readProtocolEncoding._read(this._readStream);
Protocol.checkSupportedProtocolEncoding(this._readProtocolEncoding);
const encodingVersion = new EncodingVersion();
encodingVersion._read(this._readStream);
if (
encodingVersion.major != Protocol.currentProtocolEncoding.major ||
protocolVersion.minor != Protocol.currentProtocolEncoding.minor
) {
throw new MarshalException(
`Invalid protocol encoding version in message header: ${encodingVersion.major}.${encodingVersion.minor}`,
);
}

this._readStream.readByte(); // messageType
this._readStream.readByte(); // compress
const size = this._readStream.readInt();
if (size < Protocol.headerSize) {
throw new IllegalMessageSizeException();
throw new MarshalException(`Received Ice message with unexpected size ${size}.`);
}

if (size > this._messageSizeMax) {
Expand Down Expand Up @@ -731,9 +749,8 @@ export class ConnectionI {
if (
!(
this._exception instanceof CloseConnectionException ||
this._exception instanceof ConnectionManuallyClosedException ||
this._exception instanceof ConnectionAbortedException ||
this._exception instanceof ConnectionClosedException ||
this._exception instanceof ConnectionIdleException ||
this._exception instanceof CommunicatorDestroyedException ||
this._exception instanceof ObjectAdapterDeactivatedException
)
Expand Down Expand Up @@ -906,9 +923,8 @@ export class ConnectionI {
if (
!(
this._exception instanceof CloseConnectionException ||
this._exception instanceof ConnectionManuallyClosedException ||
this._exception instanceof ConnectionAbortedException ||
this._exception instanceof ConnectionClosedException ||
this._exception instanceof ConnectionIdleException ||
this._exception instanceof CommunicatorDestroyedException ||
this._exception instanceof ObjectAdapterDeactivatedException ||
(this._exception instanceof ConnectionLostException && this._state === StateClosing)
Expand Down Expand Up @@ -1088,7 +1104,13 @@ export class ConnectionI {
`connection aborted by the idle check because it did not receive any bytes for ${idleTimeout}s\n${this._transceiver.toString()}`,
);
}
this.setState(StateClosed, new ConnectionIdleException());
this.setState(
StateClosed,
new ConnectionAbortedException(
`Connection aborted by the idle check because it did not receive any bytes for ${idleTimeout}s.`,
false,
),
);
}
// else nothing to do
}
Expand Down Expand Up @@ -1178,22 +1200,42 @@ export class ConnectionI {
m[2] !== Protocol.magic[2] ||
m[3] !== Protocol.magic[3]
) {
throw new BadMagicException("", m);
throw new ProtocolException(
`Bad magic in message header: ${m[0].toString(16)} ${m[1].toString(16)} ${m[2].toString(16)} ${m[3].toString(16)}`,
);
}

this._readProtocol._read(this._readStream);
Protocol.checkSupportedProtocol(this._readProtocol);
const protocolVersion = new ProtocolVersion();
protocolVersion._read(this._readStream);
if (
protocolVersion.major != Protocol.currentProtocol.major ||
protocolVersion.minor != Protocol.currentProtocol.minor
) {
throw new MarshalException(
`Invalid protocol version in message header: ${protocolVersion.major}.${protocolVersion.minor}`,
);
}

this._readProtocolEncoding._read(this._readStream);
Protocol.checkSupportedProtocolEncoding(this._readProtocolEncoding);
const encodingVersion = new EncodingVersion();
encodingVersion._read(this._readStream);
if (
encodingVersion.major != Protocol.currentProtocolEncoding.major ||
protocolVersion.minor != Protocol.currentProtocolEncoding.minor
) {
throw new MarshalException(
`Invalid protocol encoding version in message header: ${encodingVersion.major}.${encodingVersion.minor}`,
);
}

const messageType = this._readStream.readByte();
if (messageType !== Protocol.validateConnectionMsg) {
throw new ConnectionNotValidatedException();
throw new ProtocolException(
`Received message of type ${messageType} over a connection that is not yet validated.`,
);
}
this._readStream.readByte(); // Ignore compression status for validate connection.
if (this._readStream.readInt() !== Protocol.headerSize) {
throw new IllegalMessageSizeException();
throw new MarshalException(`Received ValidateConnection message with unexpected size ${size}.`);
}
TraceUtil.traceRecv(this._readStream, this._logger, this._traceLevels);

Expand Down Expand Up @@ -1386,11 +1428,11 @@ export class ConnectionI {
);
} else {
TraceUtil.traceRecv(info.stream, this._logger, this._traceLevels);
info.invokeNum = info.stream.readInt();
const requestCount = info.stream.readInt();
if (info.invokeNum < 0) {
info.invokeNum = 0;
throw new UnmarshalOutOfBoundsException();
throw new MarshalException(`Received batch request with ${requestCount} batches.`);
}
info.invokeNum = requestCount;
info.servantManager = this._servantManager;
info.adapter = this._adapter;
this._upcallCount += info.invokeNum;
Expand Down Expand Up @@ -1427,7 +1469,7 @@ export class ConnectionI {
this._logger,
this._traceLevels,
);
throw new UnknownMessageException();
throw new ProtocolException(`Received Ice protocol message with unknown type: ${messageType}`);
}
}
} catch (ex) {
Expand Down Expand Up @@ -1472,8 +1514,11 @@ export class ConnectionI {
// An Error was raised outside of servant code (i.e., by Ice code).
// Attempt to log the error and clean up.
//
this._logger.error("unexpected exception:\n" + ex.toString());
this.dispatchException(new UnknownException(ex), invokeNum);
this._logger.error(`unexpected exception:\n ${ex}`);
this.dispatchException(
new UnknownException("unexpected exception dispatching request", { cause: ex }),
invokeNum,
);
}
}
}
Expand Down
6 changes: 2 additions & 4 deletions js/src/Ice/DefaultsAndOverrides.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { FormatType } from "./FormatType.js";
import { EndpointSelectionType } from "./EndpointSelectionType.js";
import { Protocol, stringToEncodingVersion, encodingVersionToString } from "./Protocol.js";
import { EndpointSelectionTypeParseException } from "./LocalExceptions.js";
import { ParseException } from "./LocalExceptions.js";
import { TcpTransceiver } from "./TcpTransceiver.js";

export class DefaultsAndOverrides {
Expand All @@ -29,9 +29,7 @@ export class DefaultsAndOverrides {
} else if (value === "Ordered") {
this.defaultEndpointSelection = EndpointSelectionType.Ordered;
} else {
const ex = new EndpointSelectionTypeParseException();
ex.str = "illegal value `" + value + "'; expected 'Random' or 'Ordered'";
throw ex;
throw new ParseException(`illegal value '${value}'; expected 'Random' or 'Ordered'`);
}

this.defaultLocatorCacheTimeout = properties.getPropertyAsIntWithDefault("Ice.Default.LocatorCacheTimeout", -1);
Expand Down
12 changes: 5 additions & 7 deletions js/src/Ice/EndpointFactoryManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Copyright (c) ZeroC, Inc. All rights reserved.
//

import { EndpointParseException } from "./LocalExceptions.js";
import { ParseException } from "./LocalExceptions.js";
import { StringUtil } from "./StringUtil.js";
import { OpaqueEndpointI } from "./OpaqueEndpoint.js";
import { Protocol } from "./Protocol.js";
Expand All @@ -27,12 +27,12 @@ export class EndpointFactoryManager {
create(str, oaEndpoint) {
const s = str.trim();
if (s.length === 0) {
throw new EndpointParseException("value has no non-whitespace characters");
throw new ParseException("value has no non-whitespace characters");
}

const arr = StringUtil.splitString(s, " \t\n\r");
if (arr.length === 0) {
throw new EndpointParseException("value has no non-whitespace characters");
throw new ParseException("value has no non-whitespace characters");
}

let protocol = arr[0];
Expand All @@ -45,9 +45,7 @@ export class EndpointFactoryManager {
if (this._factories[i].protocol() === protocol) {
const e = this._factories[i].create(arr, oaEndpoint);
if (arr.length > 0) {
throw new EndpointParseException(
"unrecognized argument `" + arr[0] + "' in endpoint `" + str + "'",
);
throw new ParseException(`unrecognized argument '${arr[0]}' in endpoint '${str}'`);
}
return e;
}
Expand All @@ -61,7 +59,7 @@ export class EndpointFactoryManager {
const ue = new OpaqueEndpointI();
ue.initWithOptions(arr);
if (arr.length > 0) {
throw new EndpointParseException("unrecognized argument `" + arr[0] + "' in endpoint `" + str + "'");
throw new ParseException(`unrecognized argument '${arr[0]}' in endpoint '${str}'`);
}

for (let i = 0, length = this._factories.length; i < length; ++i) {
Expand Down
19 changes: 11 additions & 8 deletions js/src/Ice/ExUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@
// Copyright (c) ZeroC, Inc. All rights reserved.
//

import { UnexpectedObjectException, MemoryLimitException } from "./LocalExceptions.js";
import { MarshalException } from "./LocalExceptions.js";
import { UnknownSlicedValue } from "./UnknownSlicedValue.js";

export function throwUOE(expectedType, v) {
const type = v.ice_id();
throw new UnexpectedObjectException(
"expected element of type `" + expectedType + "' but received `" + type + "'",
type,
expectedType,
// If the object is an unknown sliced object, we didn't find a value factory.
if (v instanceof UnknownSlicedValue) {
throw new MarshalException(`Cannot find value factory to unmarshal class with type ID '${v.ice_id()}'.`);
}

throw new MarshalException(
`Failed to unmarshal class with type ID '${expectedType}': value factory returned class with type ID '${v.ice_id()}'.`,
);
}

export function throwMemoryLimitException(requested, maximum) {
throw new MemoryLimitException(
"requested " + requested + " bytes, maximum allowed is " + maximum + " bytes (see Ice.MessageSizeMax)",
throw new MarshalException(
`Cannot unmarshal Ice message: the message size of ${requested} bytes exceeds the maximum allowed of ${maximum} bytes (see Ice.MessageSizeMax).`,
);
}
Loading

0 comments on commit 806f28c

Please sign in to comment.