Skip to content

Commit bb7c1c1

Browse files
authored
chore: schema code size optimization (#1681)
* chore: schema code size optimization * test types and other fixes
1 parent b2c8dfa commit bb7c1c1

19 files changed

+290
-321
lines changed

.changeset/pink-items-shake.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@smithy/types": minor
3+
"@smithy/core": minor
4+
---
5+
6+
schema code size optimizations

packages/core/src/submodules/cbor/SmithyRpcV2CborProtocol.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ describe(SmithyRpcV2CborProtocol.name, () => {
153153
const protocol = new SmithyRpcV2CborProtocol({ defaultNamespace: "" });
154154
const httpRequest = await protocol.serializeRequest(
155155
{
156+
namespace: "ns",
156157
name: "dummy",
157158
input: testCase.schema,
158159
output: "unit",
@@ -256,6 +257,7 @@ describe(SmithyRpcV2CborProtocol.name, () => {
256257
});
257258
const output = await protocol.deserializeResponse(
258259
{
260+
namespace: "ns",
259261
name: "dummy",
260262
input: "unit",
261263
output: testCase.schema,

packages/core/src/submodules/cbor/SmithyRpcV2CborProtocol.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { RpcProtocol } from "@smithy/core/protocols";
2-
import type { ErrorSchema, OperationSchema } from "@smithy/core/schema";
2+
import type { ErrorSchema } from "@smithy/core/schema";
33
import { deref, NormalizedSchema, TypeRegistry } from "@smithy/core/schema";
44
import type {
55
EndpointBearer,
66
HandlerExecutionContext,
77
HttpRequest as IHttpRequest,
88
HttpResponse as IHttpResponse,
99
MetadataBearer,
10+
OperationSchema,
1011
ResponseMetadata,
1112
SerdeFunctions,
1213
} from "@smithy/types";

packages/core/src/submodules/protocols/HttpBindingProtocol.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ describe(HttpBindingProtocol.name, () => {
6464
const response = new HttpResponse({
6565
statusCode: 200,
6666
headers: {
67-
"x-timestamplist": "Mon, 16 Dec 2019 23:48:18 GMT, Mon, 16 Dec 2019 23:48:18 GMT",
67+
"x-timestamplist": "Mon, 16 Nov 2019 23:48:18 GMT, Mon, 16 Dec 2019 23:48:18 GMT",
6868
},
6969
});
7070

@@ -95,7 +95,7 @@ describe(HttpBindingProtocol.name, () => {
9595
)) as Partial<MetadataBearer>;
9696
delete output.$metadata;
9797
expect(output).toEqual({
98-
timestampList: [new Date("2019-12-16T23:48:18.000Z"), new Date("2019-12-16T23:48:18.000Z")],
98+
timestampList: [new Date("2019-11-16T23:48:18.000Z"), new Date("2019-12-16T23:48:18.000Z")],
9999
});
100100
});
101101

packages/core/src/submodules/protocols/HttpBindingProtocol.ts

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -157,20 +157,15 @@ export abstract class HttpBindingProtocol extends HttpProtocol {
157157
if (traits.httpQueryParams) {
158158
for (const [key, val] of Object.entries(data)) {
159159
if (!(key in query)) {
160-
this.serializeQuery(
161-
NormalizedSchema.of([
162-
ns.getValueSchema(),
163-
{
164-
// We pass on the traits to the sub-schema
165-
// because we are still in the process of serializing the map itself.
166-
...traits,
167-
httpQuery: key,
168-
httpQueryParams: undefined,
169-
},
170-
]),
171-
val,
172-
query
173-
);
160+
const valueSchema = ns.getValueSchema();
161+
Object.assign(valueSchema.getMergedTraits(), {
162+
// We pass on the traits to the sub-schema
163+
// because we are still in the process of serializing the map itself.
164+
...traits,
165+
httpQuery: key,
166+
httpQueryParams: undefined,
167+
});
168+
this.serializeQuery(valueSchema, val, query);
174169
}
175170
}
176171
return;
@@ -305,6 +300,7 @@ export abstract class HttpBindingProtocol extends HttpProtocol {
305300
if (null != value) {
306301
if (memberSchema.isListSchema()) {
307302
const headerListValueSchema = memberSchema.getValueSchema();
303+
headerListValueSchema.getMergedTraits().httpHeader = key;
308304
let sections: string[];
309305
if (
310306
headerListValueSchema.isTimestampSchema() &&
@@ -316,7 +312,7 @@ export abstract class HttpBindingProtocol extends HttpProtocol {
316312
}
317313
const list = [];
318314
for (const section of sections) {
319-
list.push(await deserializer.read([headerListValueSchema, { httpHeader: key }], section.trim()));
315+
list.push(await deserializer.read(headerListValueSchema, section.trim()));
320316
}
321317
dataObject[memberName] = list;
322318
} else {
@@ -327,8 +323,10 @@ export abstract class HttpBindingProtocol extends HttpProtocol {
327323
dataObject[memberName] = {};
328324
for (const [header, value] of Object.entries(response.headers)) {
329325
if (header.startsWith(memberTraits.httpPrefixHeaders)) {
326+
const valueSchema = memberSchema.getValueSchema();
327+
valueSchema.getMergedTraits().httpHeader = header;
330328
dataObject[memberName][header.slice(memberTraits.httpPrefixHeaders.length)] = await deserializer.read(
331-
[memberSchema.getValueSchema(), { httpHeader: header }],
329+
valueSchema,
332330
value
333331
);
334332
}

packages/core/src/submodules/protocols/serde/FromStringShapeDeserializer.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,18 @@ export class FromStringShapeDeserializer implements ShapeDeserializer<string> {
2929

3030
public read(_schema: Schema, data: string): any {
3131
const ns = NormalizedSchema.of(_schema);
32+
3233
if (ns.isListSchema()) {
3334
return splitHeader(data).map((item) => this.read(ns.getValueSchema(), item));
3435
}
36+
3537
if (ns.isBlobSchema()) {
3638
return (this.serdeContext?.base64Decoder ?? fromBase64)(data);
3739
}
40+
3841
if (ns.isTimestampSchema()) {
3942
const format = determineTimestampFormat(ns, this.settings);
43+
4044
switch (format) {
4145
case SCHEMA.TIMESTAMP_DATE_TIME:
4246
return parseRfc3339DateTimeWithOffset(data);

packages/core/src/submodules/protocols/serde/determineTimestampFormat.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export function determineTimestampFormat(
2929
}
3030

3131
const { httpLabel, httpPrefixHeaders, httpHeader, httpQuery } = ns.getMergedTraits();
32+
3233
const bindingFormat = settings.httpBindings
3334
? typeof httpPrefixHeaders === "string" || Boolean(httpHeader)
3435
? SCHEMA.TIMESTAMP_HTTP_DATE
Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { SchemaRef, SchemaTraits } from "@smithy/types";
22

33
import { TypeRegistry } from "../TypeRegistry";
4+
import { Schema } from "./Schema";
45
import { StructureSchema } from "./StructureSchema";
56

67
/**
@@ -12,30 +13,9 @@ import { StructureSchema } from "./StructureSchema";
1213
* @alpha
1314
*/
1415
export class ErrorSchema extends StructureSchema {
15-
public static symbol = Symbol.for("@smithy/core/schema::ErrorSchema");
16-
protected symbol = ErrorSchema.symbol;
17-
18-
public constructor(
19-
public name: string,
20-
public traits: SchemaTraits,
21-
public memberNames: string[],
22-
public memberList: SchemaRef[],
23-
/**
24-
* Constructor for a modeled service exception class that extends Error.
25-
*/
26-
public ctor: any
27-
) {
28-
super(name, traits, memberNames, memberList);
29-
}
30-
31-
public static [Symbol.hasInstance](lhs: unknown): lhs is ErrorSchema {
32-
const isPrototype = ErrorSchema.prototype.isPrototypeOf(lhs as any);
33-
if (!isPrototype && typeof lhs === "object" && lhs !== null) {
34-
const err = lhs as ErrorSchema;
35-
return err.symbol === ErrorSchema.symbol;
36-
}
37-
return isPrototype;
38-
}
16+
public static readonly symbol = Symbol.for("@smithy/err");
17+
public ctor!: any;
18+
protected readonly symbol = ErrorSchema.symbol;
3919
}
4020

4121
/**
@@ -50,15 +30,19 @@ export class ErrorSchema extends StructureSchema {
5030
* @param memberList - list of schemaRef corresponding to each
5131
* @param ctor - class reference for the existing Error extending class.
5232
*/
53-
export function error(
33+
export const error = (
5434
namespace: string,
5535
name: string,
56-
traits: SchemaTraits = {},
36+
traits: SchemaTraits,
5737
memberNames: string[],
5838
memberList: SchemaRef[],
5939
ctor: any
60-
): ErrorSchema {
61-
const schema = new ErrorSchema(namespace + "#" + name, traits, memberNames, memberList, ctor);
62-
TypeRegistry.for(namespace).register(name, schema);
63-
return schema;
64-
}
40+
): ErrorSchema =>
41+
Schema.assign(new ErrorSchema(), {
42+
name,
43+
namespace,
44+
traits,
45+
memberNames,
46+
memberList,
47+
ctor,
48+
});
Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { ListSchema as IListSchema, SchemaRef, SchemaTraits } from "@smithy/types";
22

3-
import { TypeRegistry } from "../TypeRegistry";
43
import { Schema } from "./Schema";
54

65
/**
@@ -10,38 +9,22 @@ import { Schema } from "./Schema";
109
* @alpha
1110
*/
1211
export class ListSchema extends Schema implements IListSchema {
13-
public static symbol = Symbol.for("@smithy/core/schema::ListSchema");
14-
protected symbol = ListSchema.symbol;
15-
16-
public constructor(
17-
public name: string,
18-
public traits: SchemaTraits,
19-
public valueSchema: SchemaRef
20-
) {
21-
super(name, traits);
22-
}
23-
24-
public static [Symbol.hasInstance](lhs: unknown): lhs is ListSchema {
25-
const isPrototype = ListSchema.prototype.isPrototypeOf(lhs as any);
26-
if (!isPrototype && typeof lhs === "object" && lhs !== null) {
27-
const list = lhs as ListSchema;
28-
return list.symbol === ListSchema.symbol;
29-
}
30-
return isPrototype;
31-
}
12+
public static readonly symbol = Symbol.for("@smithy/lis");
13+
public name!: string;
14+
public traits!: SchemaTraits;
15+
public valueSchema!: SchemaRef;
16+
protected readonly symbol = ListSchema.symbol;
3217
}
3318

3419
/**
3520
* Factory for ListSchema.
3621
*
3722
* @internal
3823
*/
39-
export function list(namespace: string, name: string, traits: SchemaTraits = {}, valueSchema: SchemaRef): ListSchema {
40-
const schema = new ListSchema(
41-
namespace + "#" + name,
24+
export const list = (namespace: string, name: string, traits: SchemaTraits, valueSchema: SchemaRef): ListSchema =>
25+
Schema.assign(new ListSchema(), {
26+
name,
27+
namespace,
4228
traits,
43-
typeof valueSchema === "function" ? valueSchema() : valueSchema
44-
);
45-
TypeRegistry.for(namespace).register(name, schema);
46-
return schema;
47-
}
29+
valueSchema,
30+
});
Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,38 @@
11
import type { MapSchema as IMapSchema, SchemaRef, SchemaTraits } from "@smithy/types";
22

3-
import { TypeRegistry } from "../TypeRegistry";
43
import { Schema } from "./Schema";
54

65
/**
76
* A schema with a key schema and value schema.
87
* @alpha
98
*/
109
export class MapSchema extends Schema implements IMapSchema {
11-
public static symbol = Symbol.for("@smithy/core/schema::MapSchema");
12-
protected symbol = MapSchema.symbol;
13-
14-
public constructor(
15-
public name: string,
16-
public traits: SchemaTraits,
17-
/**
18-
* This is expected to be StringSchema, but may have traits.
19-
*/
20-
public keySchema: SchemaRef,
21-
public valueSchema: SchemaRef
22-
) {
23-
super(name, traits);
24-
}
25-
26-
public static [Symbol.hasInstance](lhs: unknown): lhs is MapSchema {
27-
const isPrototype = MapSchema.prototype.isPrototypeOf(lhs as any);
28-
if (!isPrototype && typeof lhs === "object" && lhs !== null) {
29-
const map = lhs as MapSchema;
30-
return map.symbol === MapSchema.symbol;
31-
}
32-
return isPrototype;
33-
}
10+
public static readonly symbol = Symbol.for("@smithy/map");
11+
public name!: string;
12+
public traits!: SchemaTraits;
13+
/**
14+
* This is expected to be StringSchema, but may have traits.
15+
*/
16+
public keySchema!: SchemaRef;
17+
public valueSchema!: SchemaRef;
18+
protected readonly symbol = MapSchema.symbol;
3419
}
3520

3621
/**
3722
* Factory for MapSchema.
3823
* @internal
3924
*/
40-
export function map(
25+
export const map = (
4126
namespace: string,
4227
name: string,
43-
traits: SchemaTraits = {},
28+
traits: SchemaTraits,
4429
keySchema: SchemaRef,
4530
valueSchema: SchemaRef
46-
): MapSchema {
47-
const schema = new MapSchema(
48-
namespace + "#" + name,
31+
): MapSchema =>
32+
Schema.assign(new MapSchema(), {
33+
name,
34+
namespace,
4935
traits,
5036
keySchema,
51-
typeof valueSchema === "function" ? valueSchema() : valueSchema
52-
);
53-
TypeRegistry.for(namespace).register(name, schema);
54-
return schema;
55-
}
37+
valueSchema,
38+
});

0 commit comments

Comments
 (0)