├── LICENSE
├── README.md
├── bootstrap.js
├── bootstrap.ts
├── index.css
├── index.html
├── lib
├── backdrop.webp
├── codemirror.d.ts
├── filesaver.d.ts
├── jszip.d.ts
├── lib.d.ts
├── lib.dom.d.ts
├── lib.es2015.collection.d.ts
├── lib.es2015.core.d.ts
├── lib.es2015.d.ts
├── lib.es2015.generator.d.ts
├── lib.es2015.iterable.d.ts
├── lib.es2015.promise.d.ts
├── lib.es2015.proxy.d.ts
├── lib.es2015.reflect.d.ts
├── lib.es2015.symbol.d.ts
├── lib.es2015.symbol.wellknown.d.ts
├── lib.es5.d.ts
├── lib.typetalk.d.ts
└── typescript.d.ts
├── src
├── Browser.tsx
├── ClockRunnable.tsx
├── EditorComponent.tsx
├── EditorRunnable.tsx
├── GameRunnable.tsx
├── GameTestRunnable.tsx
├── HelloWorldRunnable.tsx
├── Observable.tsx
├── ProgressDialogue.tsx
├── QueryDialogue.tsx
├── RunTestsRunnable.tsx
├── Runnable.tsx
├── jsx
│ ├── DomAttributes.tsx
│ ├── HTMLComponentElement.tsx
│ ├── HtmlAttributes.tsx
│ ├── JsxDraggable.tsx
│ ├── JsxDraggableProps.tsx
│ ├── JsxGrid.tsx
│ ├── JsxGridProps.tsx
│ ├── JsxHBox.tsx
│ ├── JsxVBox.tsx
│ ├── JsxWindow.tsx
│ ├── JsxWindowProps.tsx
│ ├── UiComponent.tsx
│ ├── UiComponentConstructor.tsx
│ └── UiEventHandler.tsx
└── tests
│ ├── AbstractTest.tsx
│ ├── RemoveMethodBelongingToSuperclassTest.tsx
│ ├── SuperKeywordInConstructorTest.tsx
│ ├── SuperKeywordInMethodTest.tsx
│ ├── UpdateClassConstructorTest.tsx
│ ├── UpdateClassMethodTest.tsx
│ ├── UpdateSuperclassConstructorTest.tsx
│ └── UpdateSuperclassMethodTest.tsx
└── tsconfig.json
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | TypeTalk
2 | ========
3 |
4 | What?
5 | -----
6 |
7 | This is a proof-of-concept of a SmallTalk like live coding system running in the
8 | browser, based on TypeScript. There's no server side component at all (other
9 | than delivering static files). It'll let you update your code in a built-in
10 | editor and it'll hot-patch the running system so that your code starts
11 | working immediately, _even_ if there are objects existing which currently
12 | running it.
13 |
14 | Watch me talk about it!
15 |
16 |
17 |
18 | [Or use the version hosted on cowlark.com if you want to try it for
19 | real!](http://cowlark.com/typetalk/live.html)
20 |
21 |
22 | Why?
23 | ----
24 |
25 | It's an attempt to replicate the classic SmallTalk/Lisp paradigm which don't
26 | distinguish between users and programmers: you can, if you wish, take the lid
27 | off the application suite you're currently using and tinker with it, without
28 | recompilation, restarts, or even having to save your work.
29 |
30 | Currently it's a pile of fairly nasty hacks flying in loose formation, but it
31 | does actually _work_. Mostly.
32 |
33 |
34 | Where?
35 | ------
36 |
37 | It's [hosted on GitHub](https://github.com/davidgiven/typetalk).
38 |
39 |
40 | How?
41 | ----
42 |
43 | It uses the TypeScript LanguageServices API to do code transformation and
44 | compilation into Javascript. Your TypeScript is rewritten to match TypeTalk's
45 | kinda weird object model, loaded, and methods are hot-patched into the
46 | objects already existing on the system.
47 |
48 | There are limitations: TypeTalk 'files' may each contain a single class or
49 | interface, nothing else. So, type definitions, enums etc don't work. You
50 | can't have static initialisers. You _can_ inherit from normal Javascript
51 | objects, but it's dodgy as hell.
52 |
53 | There's no documentation other than this page.
54 |
55 | To use, simply serve this directory in a web server and load the `index.html`
56 | page. No build stage is needed. The big files are deployed via CDN.
57 |
58 | Please note that I developed it on Chrome, and it currently doesn't work on
59 | Firefox; I don't know why. Something to do with scoping and `with{}`, I
60 | think. TypeTalk's code generation appears to cause Firefox's debugger to go
61 | nuts which makes it very hard to debug.
62 |
63 |
64 | Who?
65 | ----
66 |
67 | Everything here _except_ the contents of `lib` was written by me, David
68 | Given. Feel free to send me an email at
69 | [dg@cowlark.com](mailto:dg@cowlark.com). You may also [like to visit my
70 | website](http://cowlark.com); there may or may not be something interesting
71 | there.
72 |
73 | All of my stuff is © 2019 David Given and is open source software
74 | distributable under the terms of the [Apache
75 | License](https://github.com/davidgiven/typetalk/blob/master/LICENSE).
76 |
77 | The contents of `lib` contain TypeScript typings files, which are a mixture
78 | of Apache license or MIT depending whether they came from Microsoft or
79 | DefinitelyTyped. See the file headers for more information. Some of them have
80 | had tiny tweaks to remove namespace exports (as TypeTalk doesn't use
81 | modules).
82 |
83 | The backdrop is by [jojo-ojoj from
84 | DeviantArt](https://www.deviantart.com/jojo-ojoj/art/Old-paper-seamless-textures-507236128).
85 |
--------------------------------------------------------------------------------
/bootstrap.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | "use strict";
3 |
4 | var remaining = 0;
5 | var scripts = {};
6 | function loaded_cb() {
7 | if ((remaining == 0) && (window.ts != undefined)) {
8 | var ts = scripts["bootstrap.ts"].text;
9 | var js = window.ts.transpileModule(ts, {
10 | compilerOptions: {
11 | extendedDiagnostics: true,
12 | strict: true,
13 | target: window.ts.ScriptTarget.ES2017,
14 | }
15 | });
16 | js.outputText += "\n//# sourceURL=bootstrap.js";
17 | new Function(js.outputText)();
18 | }
19 | }
20 |
21 | var allscripts = document.getElementsByTagName("SCRIPT");
22 | for (var i = 0; i < allscripts.length; i++) {
23 | (function () {
24 | var script = allscripts[i];
25 | var type = script.getAttribute("type");
26 | if (type && type.startsWith("typetalk-")) {
27 | remaining++;
28 | var x = new XMLHttpRequest();
29 | x.onreadystatechange = function () {
30 | if (this.readyState == 4) {
31 | if (this.status == 200) {
32 | script.text = this.responseText;
33 | script.leafName = script.src.replace(/.*\//, "");
34 | scripts[script.leafName] = script;
35 | remaining--;
36 | loaded_cb();
37 | } else {
38 | console.log("bootstrap failed for " + script.src);
39 | }
40 | }
41 | };
42 | x.open("GET", script.src, true);
43 | x.send();
44 | }
45 | })();
46 | }
47 |
48 | window.addEventListener("load", loaded_cb);
49 | })();
50 |
--------------------------------------------------------------------------------
/bootstrap.ts:
--------------------------------------------------------------------------------
1 | declare namespace ts {
2 | function createDiagnosticForNodeInSourceFile(
3 | sourceFile: SourceFile,
4 | node: Node,
5 | message: DiagnosticMessage,
6 | arg0?: string | number,
7 | arg1?: string | number,
8 | arg2?: string | number,
9 | arg3?: string | number): DiagnosticWithLocation;
10 | }
11 |
12 | let compilerOptions: ts.CompilerOptions = {
13 | target: ts.ScriptTarget.ES2017,
14 | downlevelIteration: true,
15 | strict: true,
16 | suppressOutputPathCheck: false,
17 | extendedDiagnostics: true,
18 | jsx: ts.JsxEmit.React,
19 | jsxFactory: "jsx",
20 | noImplicitAny: false,
21 | };
22 |
23 | let languageServiceHost;
24 | let languageService;
25 | let id = 0;
26 |
27 | let ttcontext: any = {};
28 | Object.setPrototypeOf(ttcontext, window);
29 |
30 | (Object as any).prototype.__constructor = (...args) => { };
31 |
32 | ttcontext.TTObject = class TTObject {
33 | constructor(...args) {
34 | (this as any).__constructor(...args);
35 | }
36 | };
37 |
38 | ttcontext.nativeConstructor = (theInstance: any, theClass: any, ...args: any) => {
39 | theClass.prototype.constructor.bind(theInstance)(...args);
40 | };
41 |
42 | function createClass(name: string) {
43 | let fn = new Function(`
44 | return function ${name}(...args) {
45 | this.__constructor(...args);
46 | };
47 | `)();
48 | id++;
49 | Object.defineProperty(fn, "__id", { enumerable: false, value: id });
50 | Object.defineProperty(fn.prototype, "__id", { enumerable: false, value: id });
51 | return fn;
52 | }
53 |
54 | let TTClassImpl = ttcontext.TTClass = createClass("TTClass");
55 | Object.setPrototypeOf(TTClassImpl, TTClassImpl.prototype);
56 | let typetalk = ttcontext.TypeTalk = createClass("TypeTalk");
57 | Object.setPrototypeOf(typetalk, TTClassImpl.prototype);
58 | let classes = new Map();
59 |
60 | let projectVersion = 0;
61 | TTClassImpl.prototype._typescript = "";
62 | TTClassImpl.prototype._typescriptVersion = 0;
63 | TTClassImpl.prototype._javascript = "";
64 | TTClassImpl.prototype._javascriptDirty = true;
65 | TTClassImpl.prototype._errors = [];
66 |
67 | TTClassImpl.prototype.setSource = function (typescript) {
68 | if (this._typescript != typescript) {
69 | this._typescript = typescript;
70 | this._typescriptVersion++;
71 | this._javascriptDirty = true;
72 | this._errors = [];
73 | projectVersion++;
74 | fireSubscribers();
75 | }
76 | }
77 |
78 | TTClassImpl.prototype.getSource = function () {
79 | return this._typescript;
80 | }
81 |
82 | TTClassImpl.prototype.getCommitted = function () {
83 | return !this._javascriptDirty;
84 | }
85 |
86 | TTClassImpl.prototype.getErrors = function () {
87 | return this._errors;
88 | }
89 |
90 | let subscribers = new Set();
91 | function fireSubscribers() {
92 | for (let subscriber of subscribers)
93 | setTimeout(() => subscriber.onClassesChanged(), 0);
94 | subscribers.clear();
95 | }
96 |
97 | TTClassImpl.subscribe = function (subscriber) {
98 | subscribers.add(subscriber);
99 | }
100 |
101 | TTClassImpl.addClass = function (name) {
102 | let ttclass = classes.get(name);
103 | if (!ttclass) {
104 | ttclass = createClass(name);
105 | Object.setPrototypeOf(ttclass, TTClassImpl.prototype);
106 | classes.set(name, ttclass);
107 | ttcontext[name] = ttclass;
108 | fireSubscribers();
109 | }
110 | return ttclass;
111 | }
112 |
113 | TTClassImpl.getClass = function (name) {
114 | return classes.get(name);
115 | }
116 |
117 | TTClassImpl.getAllClasses = function () {
118 | return classes;
119 | }
120 |
121 | TTClassImpl.recompile = function () {
122 | let errors = false;
123 |
124 | /* Phase 1: clear pending diagnostics. */
125 |
126 | for (let ttclass of classes.values())
127 | ttclass._errors = [];
128 |
129 | /* Phase 2: accumulate all diagnostics. */
130 |
131 | let diagnostics: ts.DiagnosticWithLocation[] = [];
132 | for (let ttclass of classes.values()) {
133 | let filename = `${ttclass.name}.tsx`;
134 | diagnostics = diagnostics.concat(
135 | languageService
136 | .getCompilerOptionsDiagnostics()
137 | .concat(languageService.getSyntacticDiagnostics(filename))
138 | .concat(languageService.getSemanticDiagnostics(filename))
139 | .filter(d => d.file && d.start));
140 | }
141 |
142 | /* Phase 3: attach the diagnostics to the files. */
143 |
144 | for (let d of diagnostics) {
145 | let classname = d.file.fileName.replace(/\.tsx$/, "");
146 | let ttclass = classes.get(classname);
147 | console.log(`${d.file.fileName}:${d.start} ${ts.flattenDiagnosticMessageText(d.messageText, "\n")}`);
148 | if (ttclass) {
149 | ttclass._errors.push(d);
150 | }
151 | }
152 |
153 | /* Phase 4: emit Javascript, even if we had diagnostics. This may add more diagnostics. */
154 |
155 | for (let ttclass of classes.values()) {
156 | if (!ttclass._javascriptDirty)
157 | continue;
158 |
159 | let filename = `${ttclass.name}.tsx`;
160 | console.log(`compiling ${ttclass.name}`);
161 |
162 | let output = languageService.getEmitOutput(filename);
163 | if (!output.emitSkipped) {
164 | for (let f of output.outputFiles) {
165 | if (f.name !== `${ttclass.name}.js`)
166 | throw `filename mismatch: got ${f.name}, expected ${filename}`;
167 | ttclass._javascript = f.text;
168 | }
169 | }
170 | }
171 |
172 | /* Phase 5: check all classes for diagnostics. If found, stop now. */
173 |
174 | let diagnostics_found = false;
175 | for (let ttclass of classes.values()) {
176 | if (ttclass._errors.length > 0) {
177 | diagnostics_found = true;
178 | break;
179 | }
180 | }
181 | if (diagnostics_found) {
182 | console.log("Compilation failed.");
183 | return;
184 | }
185 |
186 | /* Phase 6: reload the Javascript. */
187 |
188 | for (let ttclass of classes.values()) {
189 | if (!ttclass._javascriptDirty)
190 | continue;
191 |
192 | console.log(`loading ${ttclass.name}`);
193 |
194 | let ctx = Object.create(ttcontext);
195 | let body = `with (this) {\n\n` +
196 | `${ttclass._javascript}\n\n` +
197 | `return __tt_exported_class; }\n` +
198 | `//# sourceURL=${ttclass.name}.js`;
199 | let fn = new Function(body).bind(ctx);
200 | let classImpl = fn();
201 | if (classImpl) {
202 | Object.defineProperty(classImpl, 'name', { value: ttclass.name });
203 |
204 | /* We have to leave existing properties because they may contain static
205 | * class state. */
206 |
207 | for (let methodName of Object.getOwnPropertyNames(classImpl)) {
208 | if (methodName == "__id")
209 | continue;
210 | if ((methodName != "length") && (methodName != "name") && (methodName != "prototype"))
211 | ttclass[methodName] = classImpl[methodName];
212 | }
213 |
214 | /* Delete existing methods before updating the prototype in case a stale
215 | * method aliases one defined by a superclass. */
216 |
217 | for (let key of Object.keys(ttclass.prototype))
218 | delete ttclass.prototype[key];
219 | for (let methodName of Object.getOwnPropertyNames(classImpl.prototype)) {
220 | if (methodName == "__id")
221 | continue;
222 | ttclass.prototype[methodName] = classImpl.prototype[methodName];
223 | }
224 |
225 | /* The prototype of a `prototype` is always Object. The *actual* superclass
226 | * is the prototype of newClass itself. */
227 | let superclass = Object.getPrototypeOf(classImpl);
228 |
229 | /* Construct the chain of prototypes (this is not how ES6 classes do it). */
230 | Object.setPrototypeOf(ttclass.prototype, superclass.prototype);
231 | }
232 |
233 | ttclass._javascriptDirty = false;
234 | }
235 | };
236 |
237 | languageServiceHost = new class implements ts.LanguageServiceHost {
238 | private libraries = new Map();
239 |
240 | private classOfFile(path: string): any {
241 | return TTClassImpl.getClass(path.replace(/\.tsx$/, ""));
242 | }
243 |
244 | addLibrary(path: string, contents: string) {
245 | this.libraries.set(path, contents);
246 | }
247 |
248 | getScriptFileNames(): string[] {
249 | return Array.from(classes.keys())
250 | .map(name => `${name}.tsx`)
251 | .concat(Array.from(this.libraries.keys()));
252 | }
253 |
254 | getScriptVersion(path: string): string {
255 | if (this.libraries.has(path))
256 | return "0";
257 | return this.classOfFile(path)._typescriptVersion.toString();
258 | }
259 |
260 | getProjectVersion(): string {
261 | return projectVersion.toString();
262 | }
263 |
264 | getScriptSnapshot(path: string) {
265 | let text = this.libraries.get(path);
266 | if (text == undefined)
267 | text = this.classOfFile(path)._typescript;
268 | return ts.ScriptSnapshot.fromString(text!);
269 | }
270 |
271 | getCurrentDirectory(): string {
272 | return "";
273 | }
274 |
275 | getCompilationSettings(): any {
276 | return compilerOptions;
277 | }
278 |
279 | getDefaultLibFileName(options: any): string {
280 | return "lib.d.ts";
281 | }
282 |
283 | getCustomTransformers(): ts.CustomTransformers {
284 | return new class implements ts.CustomTransformers {
285 | before = [
286 | (context) =>
287 | (sourceFile) => sanityCheckTransformer(sourceFile).apply(),
288 | (context) =>
289 | (sourceFile) => constructorTransformer(context, sourceFile).apply()
290 | ];
291 |
292 | after = [
293 | (context) =>
294 | (sourceFile) => deconstructorTransformer(context, sourceFile).apply()
295 | ];
296 | }
297 | }
298 |
299 | trace = console.log;
300 | };
301 |
302 | languageService = ts.createLanguageService(
303 | languageServiceHost,
304 | ts.createDocumentRegistry()
305 | );
306 |
307 | function createDiagnostic(message: string) {
308 | return {
309 | key: message,
310 | category: ts.DiagnosticCategory.Error,
311 | code: 9999,
312 | message: message
313 | };
314 | };
315 |
316 | class TransformedFileWithDiagnostics {
317 | constructor(
318 | public result: ts.SourceFile,
319 | public diagnostics: ReadonlyArray) { }
320 |
321 | apply(): ts.SourceFile {
322 | for (let d of this.diagnostics) {
323 | let classname = d.file.fileName.replace(/\.tsx$/, "");
324 | let ttclass = classes.get(classname);
325 | if (ttclass)
326 | ttclass._errors.push(d);
327 | }
328 |
329 | return this.result!;
330 | }
331 | }
332 |
333 | function sanityCheckTransformer(node: ts.SourceFile): TransformedFileWithDiagnostics {
334 | let diagnostics: ts.DiagnosticWithLocation[] = [];
335 | let theClass: ts.ClassLikeDeclaration | null = null;
336 | for (let statement of node.statements) {
337 | if (ts.isClassDeclaration(statement) || ts.isInterfaceDeclaration(statement)) {
338 | if (theClass)
339 | diagnostics.push(ts.createDiagnosticForNodeInSourceFile(node, statement,
340 | createDiagnostic("TypeTalk files must contain precisely one class")));
341 | else
342 | theClass = statement as ts.ClassLikeDeclaration;
343 | } else if (ts.isEmptyStatement(statement)) {
344 | /* Do nothing, these are legal */
345 | } else
346 | diagnostics.push(ts.createDiagnosticForNodeInSourceFile(node, statement,
347 | createDiagnostic(`Illegal statement ${statement.kind}`)));
348 | }
349 |
350 | if (theClass) {
351 | for (let member of theClass.members) {
352 | if (ts.isPropertyDeclaration(member)) {
353 | let theProperty = member as ts.PropertyDeclaration;
354 | if (theProperty.modifiers && theProperty.initializer) {
355 | for (let modifier of theProperty.modifiers) {
356 | if (modifier.kind == ts.SyntaxKind.StaticKeyword) {
357 | diagnostics.push(ts.createDiagnosticForNodeInSourceFile(node, member,
358 | createDiagnostic(`Static properties in TypeTalk classes can't be initialised`)));
359 | }
360 | }
361 | }
362 | }
363 | }
364 | }
365 |
366 | return new TransformedFileWithDiagnostics(node, diagnostics);
367 | }
368 |
369 | function constructorTransformer(context: ts.TransformationContext, node: ts.SourceFile): TransformedFileWithDiagnostics {
370 | function visitor(node: ts.Node): ts.VisitResult {
371 | if (!ts.isClassDeclaration(node))
372 | return node
373 |
374 | let theClass = node as ts.ClassDeclaration;
375 | let hasConstructor = false;
376 | for (let member of theClass.members) {
377 | hasConstructor = hasConstructor || ts.isConstructorDeclaration(member);
378 | }
379 | if (hasConstructor)
380 | return node;
381 |
382 | return ts.updateClassDeclaration(
383 | theClass,
384 | theClass.decorators,
385 | theClass.modifiers,
386 | theClass.name,
387 | theClass.typeParameters,
388 | theClass.heritageClauses,
389 | theClass.members.concat(
390 | ts.createConstructor(
391 | undefined,
392 | undefined,
393 | [
394 | ts.createParameter(
395 | undefined,
396 | undefined,
397 | ts.createToken(ts.SyntaxKind.DotDotDotToken),
398 | "args"
399 | )
400 | ],
401 | ts.createBlock(
402 | [
403 | ts.createStatement(
404 | ts.createCall(
405 | ts.createSuper(),
406 | undefined,
407 | [
408 | ts.createSpread(
409 | ts.createIdentifier("args")
410 | )
411 | ]
412 | )
413 | )
414 | ]
415 | )
416 | )
417 | )
418 | );
419 | }
420 |
421 | return new TransformedFileWithDiagnostics(ts.visitEachChild(node, visitor, context), []);
422 | }
423 |
424 | function deconstructorTransformer(ctx: ts.TransformationContext, node: ts.SourceFile): TransformedFileWithDiagnostics {
425 | let diagnostics: ts.DiagnosticWithLocation[] = [];
426 | let seenClass = false;
427 | for (let statement of node.statements) {
428 | if (ts.isClassDeclaration(statement))
429 | seenClass = true;
430 | }
431 | if (!seenClass) {
432 | /* No class has been seen, which means this is an interface (which TypeScript compiles
433 | * into no code). Add a dummy declaration to keep the rest of the runtime happy. */
434 | return new TransformedFileWithDiagnostics(
435 | ts.updateSourceFileNode(
436 | node,
437 | ts.createNodeArray([
438 | ts.createExpressionStatement(
439 | ts.createAssignment(
440 | ts.createIdentifier("__tt_exported_class"),
441 | ts.createNull()
442 | )
443 | )
444 | ])
445 | ),
446 | diagnostics
447 | );
448 | }
449 |
450 | function visitConstructorNodes(node: ts.Node): ts.VisitResult {
451 | /* Don't iterate into class expressions. */
452 | if (ts.isClassLike(node))
453 | return node;
454 | if (node.kind == ts.SyntaxKind.SuperKeyword) {
455 | /* Rewrite any calls to super to super.__constructor. */
456 | return ts.createPropertyAccess(
457 | ts.createSuper(),
458 | "__constructor");
459 | }
460 | return ts.visitEachChild(node, visitConstructorNodes, ctx);
461 | }
462 |
463 | function visitMembers(node: ts.Node): ts.VisitResult {
464 | if (ts.isConstructorDeclaration(node)) {
465 | return ts.createMethod(
466 | node.decorators,
467 | node.modifiers,
468 | node.asteriskToken,
469 | "__constructor",
470 | node.questionToken,
471 | node.typeParameters,
472 | node.parameters,
473 | node.type,
474 | ts.visitEachChild((node as ts.ConstructorDeclaration).body,
475 | visitConstructorNodes, ctx));
476 | }
477 | if (ts.isClassDeclaration(node)) {
478 | let theClass = node as ts.ClassLikeDeclaration;
479 | let hasExtension = false;
480 | if (theClass.heritageClauses) {
481 | for (let clause of theClass.heritageClauses)
482 | hasExtension = hasExtension || (clause.token == ts.SyntaxKind.ExtendsKeyword);
483 | }
484 |
485 | let clauses = theClass.heritageClauses
486 | if (!hasExtension && ts.isClassDeclaration(theClass)) {
487 | if (!clauses)
488 | clauses = ts.createNodeArray();
489 | clauses = ts.createNodeArray(
490 | clauses.concat(
491 | ts.createHeritageClause(
492 | ts.SyntaxKind.ExtendsKeyword,
493 | [ts.createExpressionWithTypeArguments(
494 | undefined,
495 | ts.createIdentifier("TTObject")
496 | )]
497 | )
498 | )
499 | );
500 | }
501 |
502 | if (ts.isClassDeclaration(theClass))
503 | node = ts.updateClassDeclaration(
504 | theClass,
505 | theClass.decorators,
506 | theClass.modifiers,
507 | ts.createIdentifier("__tt_exported_class"),
508 | theClass.typeParameters,
509 | clauses,
510 | theClass.members
511 | );
512 | else if (ts.isInterfaceDeclaration(theClass))
513 | node = ts.updateInterfaceDeclaration(
514 | theClass,
515 | theClass.decorators,
516 | theClass.modifiers,
517 | ts.createIdentifier("__tt_exported_class"),
518 | theClass.typeParameters,
519 | theClass.heritageClauses,
520 | theClass.members
521 | );
522 | else
523 | throw "object is not a class or interface";
524 |
525 |
526 | return ts.visitEachChild(node, visitMembers, ctx);
527 | }
528 | if (ts.isMethodDeclaration(node) || ts.isPropertyDeclaration(node)) {
529 | return node;
530 | }
531 | return ts.visitEachChild(node, visitMembers, ctx);
532 | }
533 |
534 | return new TransformedFileWithDiagnostics(
535 | ts.visitEachChild(node, visitMembers, ctx),
536 | diagnostics
537 | );
538 | }
539 |
540 | ttcontext.globals = ttcontext;
541 |
542 | (function () {
543 | let scripts = document.getElementsByTagName("SCRIPT");
544 | for (let i = 0; i < scripts.length; i++) {
545 | let script: any = scripts[i];
546 | switch (script.getAttribute("type")) {
547 | case "typetalk-lib":
548 | languageServiceHost.addLibrary(script.leafName, script.text);
549 | break;
550 |
551 | case "typetalk-src": {
552 | let matches = /(?:class|interface) (\w+)(?: +extends (\w+))?/.exec(script.text);
553 | if (!matches)
554 | throw `script ${script.leafName} did not contain a parseable class`;
555 | let className = matches[1];
556 | let superclassName = matches[2] || null;
557 | console.log(`loading ${className}`);
558 | TTClassImpl.addClass(className).setSource(script.text);
559 | }
560 | }
561 | }
562 | })();
563 |
564 | TTClassImpl.recompile();
565 | let browser = new ttcontext.Browser();
566 |
567 | browser.run();
568 | //(async () => await browser.run())();
569 |
570 |
--------------------------------------------------------------------------------
/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | BODY {
6 | position: absolute;
7 | left: 0;
8 | top: 0;
9 | width: 100%;
10 | height: 100%;
11 | overflow: hidden;
12 | background-image: url(lib/backdrop.webp);
13 | background-repeat: repeat;
14 | }
15 |
16 | .window {
17 | display: flex;
18 | flex-direction: column;
19 | padding: 0;
20 | border: 1px solid black;
21 | background-color: white;
22 | position: absolute;
23 | box-shadow: 5px 5px 10px rgba(0, 0, 0, .5);
24 | }
25 |
26 | .window .titlebar {
27 | display: flex;
28 | flex-direction: row;
29 | flex-shrink: 0;
30 | padding: 0.3em;
31 | font-weight: bold;
32 | cursor: move;
33 | }
34 |
35 | .window .content {
36 | display: flex;
37 | flex-direction: column;
38 | flex-grow: 1;
39 | padding: 0.3em;
40 | }
41 |
42 | .window .resizer {
43 | position: absolute;
44 | right: -6px;
45 | bottom: -6px;
46 | width: 1em;
47 | height: 1em;
48 | background-color: red;
49 | cursor: nwse-resize;
50 | }
51 |
52 | .hbox {
53 | display: flex;
54 | flex-direction: row;
55 | flex-grow: 1;
56 | }
57 |
58 | .vbox {
59 | display: flex;
60 | flex-direction: column;
61 | flex-grow: 1;
62 | }
63 |
64 | .expand { flex-grow: 999; }
65 | .noexpand { flex-shrink: 0; }
66 |
67 | .editor-codecontainer {
68 | position: relative;
69 | flex-grow: 1;
70 | overflow: auto;
71 | }
72 |
73 | .CodeMirror {
74 | height: auto;
75 | position: absolute;
76 | top: 0;
77 | left: 0;
78 | right: 0;
79 | bottom: 0;
80 | z-index: 0;
81 | }
82 |
83 | .CodeMirror-error {
84 | font-size: 80% !important;
85 | background-color: #f88 !important;
86 | }
87 |
88 | button input {
89 | display: none;
90 | position: absolute;
91 | width: 0;
92 | height: 0;
93 | }
94 |
95 | .centred {
96 | position: absolute;
97 | top: 50%;
98 | left: 50%;
99 | margin-right: -50%;
100 | transform: translate(-50%, -50%);
101 | }
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | TypeTalk demo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/lib/backdrop.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidgiven/typetalk/f76c05b18e4f2d30bc0821b4fc724f4e2d0c24f1/lib/backdrop.webp
--------------------------------------------------------------------------------
/lib/filesaver.d.ts:
--------------------------------------------------------------------------------
1 | // Type definitions for FileSaver.js 2.0
2 | // Project: https://github.com/eligrey/FileSaver.js/
3 | // Definitions by: Cyril Schumacher
4 | // Daniel Roth
5 | // Chris Barr
6 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/file-saver
7 |
8 | declare namespace FileSaver {
9 | /**
10 | * FileSaver.js implements the saveAs() FileSaver interface in browsers that do not natively support it.
11 | * @param data - The actual file data blob or URL.
12 | * @param filename - The optional name of the file to be downloaded. If omitted, the name used in the file data will be used. If none is provided "download" will be used.
13 | * @param disableAutoBOM - Optional & defaults to `false`. Set to `true` if you want FileSaver.js to automatically provide Unicode text encoding hints
14 | */
15 | function saveAs(data: Blob | string, filename?: string, disableAutoBOM?: boolean): void;
16 | }
17 |
18 | declare global {
19 | const saveAs: typeof FileSaver.saveAs;
20 |
21 | interface Window {
22 | saveAs: typeof FileSaver.saveAs;
23 | }
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/lib/jszip.d.ts:
--------------------------------------------------------------------------------
1 | interface JSZip {
2 | /**
3 | * Get a file from the archive
4 | *
5 | * @param Path relative path to file
6 | * @return File matching path, null if no file found
7 | */
8 | file(path: string): JSZipObject;
9 |
10 | /**
11 | * Get files matching a RegExp from archive
12 | *
13 | * @param path RegExp to match
14 | * @return Return all matching files or an empty array
15 | */
16 | file(path: RegExp): JSZipObject[];
17 |
18 | /**
19 | * Add a file to the archive
20 | *
21 | * @param path Relative path to file
22 | * @param content Content of the file
23 | * @param options Optional information about the file
24 | * @return JSZip object
25 | */
26 | file(path: string, data: any, options?: JSZipFileOptions): JSZip;
27 |
28 | /**
29 | * Return an new JSZip instance with the given folder as root
30 | *
31 | * @param name Name of the folder
32 | * @return New JSZip object with the given folder as root or null
33 | */
34 | folder(name: string): JSZip;
35 |
36 | /**
37 | * Returns new JSZip instances with the matching folders as root
38 | *
39 | * @param name RegExp to match
40 | * @return New array of JSZipFile objects which match the RegExp
41 | */
42 | folder(name: RegExp): JSZipObject[];
43 |
44 | /**
45 | * Iterate over all files
46 | *
47 | * @param predicate Filter function
48 | * @return Array of matched elements
49 | */
50 | forEach(callback: (relativePath: string, file: JSZipObject) => void): void;
51 |
52 | /**
53 | * Get all files which match the given filter function
54 | *
55 | * @param predicate Filter function
56 | * @return Array of matched elements
57 | */
58 | filter(predicate: (relativePath: string, file: JSZipObject) => boolean): JSZipObject[];
59 |
60 | /**
61 | * Removes the file or folder from the archive
62 | *
63 | * @param path Relative path of file or folder
64 | * @return Returns the JSZip instance
65 | */
66 | remove(path: string): JSZip;
67 |
68 | /**
69 | * Generates a new archive
70 | *
71 | * @param options Options for the generator
72 | * @return Returns a Promise of the generated zip file.
73 | */
74 | generateAsync(options: JSZipGeneratorOptions, onUpdate?: JSZipMetaUpdateCallback): Promise;
75 |
76 | /**
77 | * Generates the complete zip file as a nodejs stream.
78 | *
79 | * @param options Options for the generator
80 | * @return Returns a readable stream
81 | */
82 | generateNodeStream(options: JSZipGeneratorOptions, onUpdate?: JSZipMetaUpdateCallback): NodeJS.ReadableStream
83 |
84 | /**
85 | * Generates the complete zip file with the internal stream implementation.
86 | *
87 | * @param options Options for the generator
88 | */
89 | generateInternalStream(options: JSZipGeneratorOptions): JSZipStreamHelper;
90 |
91 | /**
92 | * Deserialize zip file
93 | *
94 | * @param data Serialized zip file
95 | * @param options Options for deserializing
96 | * @return Returns the JSZip instance
97 | */
98 | loadAsync(data: any, options: JSZipLoadOptions): Promise;
99 | }
100 |
101 | interface JSZipObject {
102 | name: string;
103 | dir: boolean;
104 | date: Date;
105 | comment: string;
106 | unixPermissions: number;
107 | dosPermissions: number;
108 | options: {
109 | compression: string
110 | };
111 |
112 | async(type: string, onUpdate?: JSZipMetaUpdateCallback): Promise;
113 | nodeStream(type: string, onUpdate?: JSZipMetaUpdateCallback): NodeJS.ReadableStream;
114 | internalStream(type: string): JSZipStreamHelper;
115 | }
116 |
117 | interface JSZipFileOptions {
118 | base64?: boolean;
119 | binary?: boolean;
120 | date?: Date;
121 | compression?: string;
122 | compressionOptions?: JSZipCompressionOptions;
123 | comment?: string;
124 | optimizedBinaryString?: boolean;
125 | createFolders?: boolean;
126 | unixPermissions?: boolean;
127 | dosPermissions?: boolean;
128 | dir?: boolean;
129 | }
130 |
131 | interface JSZipGeneratorOptions {
132 | compression?: string;
133 | compressionOptions?: JSZipCompressionOptions;
134 | type?: string;
135 | comment?: string;
136 | mimeType?: string;
137 | platform?: string;
138 | encodeFileName?: (data: any) => string;
139 | streamFiles?: boolean;
140 | }
141 |
142 | interface JSZipLoadOptions {
143 | base64?: boolean;
144 | checkCRC32?: boolean;
145 | optimizedBinaryString?: boolean;
146 | createFolders?: boolean;
147 | decodeFileName?: (data: any) => string;
148 | }
149 |
150 | interface JSZipCompressionOptions {
151 | level?: number;
152 | }
153 |
154 | interface JSZipStreamHelper {
155 | on(event: "data", callback: (chunk: any, metadata: JSZipMetadata) => void): this;
156 | on(event: "error", callback: (error: Error) => void): this;
157 | on(event: "end", callback: () => void): this;
158 | on(event: string, callback: Function): this;
159 |
160 | accumulate(callback: (error: any, data: any) => void, updateCallback?: (metadata: JSZipMetadata) => void): void;
161 | resume(): this;
162 | pause(): this;
163 | }
164 |
165 | interface JSZipSupport {
166 | arraybuffer: boolean;
167 | uint8array: boolean;
168 | blob: boolean;
169 | nodebuffer: boolean;
170 | nodestream: boolean;
171 | }
172 |
173 | interface JSZipMetadata {
174 | percent: number;
175 | currentFile: string;
176 | }
177 |
178 | interface JSZipMetaUpdateCallback {
179 | (percent: number, currentFile: string): void;
180 | }
181 |
182 | declare var JSZip: {
183 | /**
184 | * Create JSZip instance
185 | */
186 | (): JSZip;
187 |
188 | /**
189 | * Create JSZip instance
190 | */
191 | new (): JSZip;
192 |
193 | prototype: JSZip;
194 | loadAsync: (data: any, options: JSZipLoadOptions) => Promise;
195 | support: JSZipSupport;
196 | external: {
197 | Promise: Object
198 | };
199 | }
200 |
201 | declare module "jszip" {
202 | export = JSZip;
203 | }
--------------------------------------------------------------------------------
/lib/lib.d.ts:
--------------------------------------------------------------------------------
1 | /*! *****************************************************************************
2 | Copyright (c) Microsoft Corporation. All rights reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 |
7 | THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8 | KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
9 | WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10 | MERCHANTABLITY OR NON-INFRINGEMENT.
11 |
12 | See the Apache Version 2.0 License for specific language governing permissions
13 | and limitations under the License.
14 | ***************************************************************************** */
15 |
16 |
17 |
18 | ///
19 |
20 |
21 | ///
22 | ///
23 |
--------------------------------------------------------------------------------
/lib/lib.es2015.collection.d.ts:
--------------------------------------------------------------------------------
1 | /*! *****************************************************************************
2 | Copyright (c) Microsoft Corporation. All rights reserved.
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | this file except in compliance with the License. You may obtain a copy of the
5 | License at http://www.apache.org/licenses/LICENSE-2.0
6 |
7 | THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8 | KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
9 | WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10 | MERCHANTABLITY OR NON-INFRINGEMENT.
11 |
12 | See the Apache Version 2.0 License for specific language governing permissions
13 | and limitations under the License.
14 | ***************************************************************************** */
15 |
16 |
17 |
18 | ///
19 |
20 |
21 | interface Map {
22 | clear(): void;
23 | delete(key: K): boolean;
24 | forEach(callbackfn: (value: V, key: K, map: Map) => void, thisArg?: any): void;
25 | get(key: K): V | undefined;
26 | has(key: K): boolean;
27 | set(key: K, value: V): this;
28 | readonly size: number;
29 | }
30 |
31 | interface MapConstructor {
32 | new(): Map;
33 | new(entries?: ReadonlyArray<[K, V]> | null): Map;
34 | readonly prototype: Map;
35 | }
36 | declare var Map: MapConstructor;
37 |
38 | interface ReadonlyMap {
39 | forEach(callbackfn: (value: V, key: K, map: ReadonlyMap) => void, thisArg?: any): void;
40 | get(key: K): V | undefined;
41 | has(key: K): boolean;
42 | readonly size: number;
43 | }
44 |
45 | interface WeakMap {
46 | delete(key: K): boolean;
47 | get(key: K): V | undefined;
48 | has(key: K): boolean;
49 | set(key: K, value: V): this;
50 | }
51 |
52 | interface WeakMapConstructor {
53 | new (entries?: ReadonlyArray<[K, V]> | null): WeakMap;
54 | readonly prototype: WeakMap