Skip to content

Commit d03ef9a

Browse files
authored
fix(smithy-client): string.toString requires this be a String (#1027)
* fix(smithy-client): string.toString requires this be a String Because of Because of microsoft/tslib#95, TS 'extends' shim doesn't support extending native types like String. So here we create StringWrapper that duplicate everything from String class including its prototype chain. So we can extend from here. * fix: typo
1 parent 3386761 commit d03ef9a

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { LazyJsonString } from "./lazy-json";
2+
describe("LazyJsonString", () => {
3+
it("should has string methods", () => {
4+
const jsonValue = new LazyJsonString('"foo"');
5+
expect(jsonValue.length).toBe(5);
6+
expect(jsonValue.toString()).toBe('"foo"');
7+
});
8+
9+
it("should deserialize json properly", () => {
10+
const jsonValue = new LazyJsonString('"foo"');
11+
expect(jsonValue.deserializeJSON()).toBe("foo");
12+
const wrongJsonValue = new LazyJsonString("foo");
13+
expect(() => wrongJsonValue.deserializeJSON()).toThrow();
14+
});
15+
16+
it("should get JSON string properly", () => {
17+
const jsonValue = new LazyJsonString('{"foo", "bar"}');
18+
expect(jsonValue.toJSON()).toBe('{"foo", "bar"}');
19+
});
20+
21+
it("can instantiate from LazyJsonString class", () => {
22+
const original = new LazyJsonString('"foo"');
23+
const newOne = LazyJsonString.fromObject(original);
24+
expect(newOne.toString()).toBe('"foo"');
25+
});
26+
27+
it("can instantiate from String class", () => {
28+
const jsonValue = LazyJsonString.fromObject(new String('"foo"'));
29+
expect(jsonValue.toString()).toBe('"foo"');
30+
});
31+
32+
it("can instantiate from object", () => {
33+
const jsonValue = LazyJsonString.fromObject({ foo: "bar" });
34+
expect(jsonValue.toString()).toBe('{"foo":"bar"}');
35+
});
36+
});

packages/smithy-client/src/lazy-json.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,38 @@
11
/**
22
* Lazy String holder for JSON typed contents.
33
*/
4-
export class LazyJsonString extends String {
4+
5+
interface StringWrapper {
6+
new (arg: any): String;
7+
}
8+
9+
/**
10+
* Because of https://github.com/microsoft/tslib/issues/95,
11+
* TS 'extends' shim doesn't support extending native types like String.
12+
* So here we create StringWrapper that duplicate everything from String
13+
* class including its prototype chain. So we can extend from here.
14+
*/
15+
// @ts-ignore StringWrapper implementation is not a simple constructor
16+
export const StringWrapper: StringWrapper = function() {
17+
//@ts-ignore 'this' cannot be assigned to any, but Object.getPrototypeOf accepts any
18+
const Class = Object.getPrototypeOf(this).constructor;
19+
const Constructor = Function.bind.apply(String, [null as any, ...arguments]);
20+
//@ts-ignore Call wrapped String constructor directly, don't bother typing it.
21+
const instance = new Constructor();
22+
Object.setPrototypeOf(instance, Class.prototype);
23+
return instance as String;
24+
};
25+
StringWrapper.prototype = Object.create(String.prototype, {
26+
constructor: {
27+
value: StringWrapper,
28+
enumerable: false,
29+
writable: true,
30+
configurable: true
31+
}
32+
});
33+
Object.setPrototypeOf(StringWrapper, String);
34+
35+
export class LazyJsonString extends StringWrapper {
536
deserializeJSON(): any {
637
return JSON.parse(super.toString());
738
}
@@ -13,7 +44,7 @@ export class LazyJsonString extends String {
1344
static fromObject(object: any): LazyJsonString {
1445
if (object instanceof LazyJsonString) {
1546
return object;
16-
} else if (object instanceof String || typeof object === 'string') {
47+
} else if (object instanceof String || typeof object === "string") {
1748
return new LazyJsonString(object);
1849
}
1950
return new LazyJsonString(JSON.stringify(object));

0 commit comments

Comments
 (0)