├── 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; 55 | } 56 | declare var WeakMap: WeakMapConstructor; 57 | 58 | interface Set { 59 | add(value: T): this; 60 | clear(): void; 61 | delete(value: T): boolean; 62 | forEach(callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: any): void; 63 | has(value: T): boolean; 64 | readonly size: number; 65 | } 66 | 67 | interface SetConstructor { 68 | new (values?: ReadonlyArray | null): Set; 69 | readonly prototype: Set; 70 | } 71 | declare var Set: SetConstructor; 72 | 73 | interface ReadonlySet { 74 | forEach(callbackfn: (value: T, value2: T, set: ReadonlySet) => void, thisArg?: any): void; 75 | has(value: T): boolean; 76 | readonly size: number; 77 | } 78 | 79 | interface WeakSet { 80 | add(value: T): this; 81 | delete(value: T): boolean; 82 | has(value: T): boolean; 83 | } 84 | 85 | interface WeakSetConstructor { 86 | new (values?: ReadonlyArray | null): WeakSet; 87 | readonly prototype: WeakSet; 88 | } 89 | declare var WeakSet: WeakSetConstructor; 90 | -------------------------------------------------------------------------------- /lib/lib.es2015.core.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 Array { 22 | /** 23 | * Returns the value of the first element in the array where predicate is true, and undefined 24 | * otherwise. 25 | * @param predicate find calls predicate once for each element of the array, in ascending 26 | * order, until it finds one where predicate returns true. If such an element is found, find 27 | * immediately returns that element value. Otherwise, find returns undefined. 28 | * @param thisArg If provided, it will be used as the this value for each invocation of 29 | * predicate. If it is not provided, undefined is used instead. 30 | */ 31 | find(predicate: (this: void, value: T, index: number, obj: T[]) => value is S, thisArg?: any): S | undefined; 32 | find(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): T | undefined; 33 | 34 | /** 35 | * Returns the index of the first element in the array where predicate is true, and -1 36 | * otherwise. 37 | * @param predicate find calls predicate once for each element of the array, in ascending 38 | * order, until it finds one where predicate returns true. If such an element is found, 39 | * findIndex immediately returns that element index. Otherwise, findIndex returns -1. 40 | * @param thisArg If provided, it will be used as the this value for each invocation of 41 | * predicate. If it is not provided, undefined is used instead. 42 | */ 43 | findIndex(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): number; 44 | 45 | /** 46 | * Returns the this object after filling the section identified by start and end with value 47 | * @param value value to fill array section with 48 | * @param start index to start filling the array at. If start is negative, it is treated as 49 | * length+start where length is the length of the array. 50 | * @param end index to stop filling the array at. If end is negative, it is treated as 51 | * length+end. 52 | */ 53 | fill(value: T, start?: number, end?: number): this; 54 | 55 | /** 56 | * Returns the this object after copying a section of the array identified by start and end 57 | * to the same array starting at position target 58 | * @param target If target is negative, it is treated as length+target where length is the 59 | * length of the array. 60 | * @param start If start is negative, it is treated as length+start. If end is negative, it 61 | * is treated as length+end. 62 | * @param end If not specified, length of the this object is used as its default value. 63 | */ 64 | copyWithin(target: number, start: number, end?: number): this; 65 | } 66 | 67 | interface ArrayConstructor { 68 | /** 69 | * Creates an array from an array-like object. 70 | * @param arrayLike An array-like object to convert to an array. 71 | */ 72 | from(arrayLike: ArrayLike): T[]; 73 | 74 | /** 75 | * Creates an array from an iterable object. 76 | * @param arrayLike An array-like object to convert to an array. 77 | * @param mapfn A mapping function to call on every element of the array. 78 | * @param thisArg Value of 'this' used to invoke the mapfn. 79 | */ 80 | from(arrayLike: ArrayLike, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; 81 | 82 | /** 83 | * Returns a new array from a set of elements. 84 | * @param items A set of elements to include in the new array object. 85 | */ 86 | of(...items: T[]): T[]; 87 | } 88 | 89 | interface DateConstructor { 90 | new (value: number | string | Date): Date; 91 | } 92 | 93 | interface Function { 94 | /** 95 | * Returns the name of the function. Function names are read-only and can not be changed. 96 | */ 97 | readonly name: string; 98 | } 99 | 100 | interface Math { 101 | /** 102 | * Returns the number of leading zero bits in the 32-bit binary representation of a number. 103 | * @param x A numeric expression. 104 | */ 105 | clz32(x: number): number; 106 | 107 | /** 108 | * Returns the result of 32-bit multiplication of two numbers. 109 | * @param x First number 110 | * @param y Second number 111 | */ 112 | imul(x: number, y: number): number; 113 | 114 | /** 115 | * Returns the sign of the x, indicating whether x is positive, negative or zero. 116 | * @param x The numeric expression to test 117 | */ 118 | sign(x: number): number; 119 | 120 | /** 121 | * Returns the base 10 logarithm of a number. 122 | * @param x A numeric expression. 123 | */ 124 | log10(x: number): number; 125 | 126 | /** 127 | * Returns the base 2 logarithm of a number. 128 | * @param x A numeric expression. 129 | */ 130 | log2(x: number): number; 131 | 132 | /** 133 | * Returns the natural logarithm of 1 + x. 134 | * @param x A numeric expression. 135 | */ 136 | log1p(x: number): number; 137 | 138 | /** 139 | * Returns the result of (e^x - 1), which is an implementation-dependent approximation to 140 | * subtracting 1 from the exponential function of x (e raised to the power of x, where e 141 | * is the base of the natural logarithms). 142 | * @param x A numeric expression. 143 | */ 144 | expm1(x: number): number; 145 | 146 | /** 147 | * Returns the hyperbolic cosine of a number. 148 | * @param x A numeric expression that contains an angle measured in radians. 149 | */ 150 | cosh(x: number): number; 151 | 152 | /** 153 | * Returns the hyperbolic sine of a number. 154 | * @param x A numeric expression that contains an angle measured in radians. 155 | */ 156 | sinh(x: number): number; 157 | 158 | /** 159 | * Returns the hyperbolic tangent of a number. 160 | * @param x A numeric expression that contains an angle measured in radians. 161 | */ 162 | tanh(x: number): number; 163 | 164 | /** 165 | * Returns the inverse hyperbolic cosine of a number. 166 | * @param x A numeric expression that contains an angle measured in radians. 167 | */ 168 | acosh(x: number): number; 169 | 170 | /** 171 | * Returns the inverse hyperbolic sine of a number. 172 | * @param x A numeric expression that contains an angle measured in radians. 173 | */ 174 | asinh(x: number): number; 175 | 176 | /** 177 | * Returns the inverse hyperbolic tangent of a number. 178 | * @param x A numeric expression that contains an angle measured in radians. 179 | */ 180 | atanh(x: number): number; 181 | 182 | /** 183 | * Returns the square root of the sum of squares of its arguments. 184 | * @param values Values to compute the square root for. 185 | * If no arguments are passed, the result is +0. 186 | * If there is only one argument, the result is the absolute value. 187 | * If any argument is +Infinity or -Infinity, the result is +Infinity. 188 | * If any argument is NaN, the result is NaN. 189 | * If all arguments are either +0 or −0, the result is +0. 190 | */ 191 | hypot(...values: number[]): number; 192 | 193 | /** 194 | * Returns the integral part of the a numeric expression, x, removing any fractional digits. 195 | * If x is already an integer, the result is x. 196 | * @param x A numeric expression. 197 | */ 198 | trunc(x: number): number; 199 | 200 | /** 201 | * Returns the nearest single precision float representation of a number. 202 | * @param x A numeric expression. 203 | */ 204 | fround(x: number): number; 205 | 206 | /** 207 | * Returns an implementation-dependent approximation to the cube root of number. 208 | * @param x A numeric expression. 209 | */ 210 | cbrt(x: number): number; 211 | } 212 | 213 | interface NumberConstructor { 214 | /** 215 | * The value of Number.EPSILON is the difference between 1 and the smallest value greater than 1 216 | * that is representable as a Number value, which is approximately: 217 | * 2.2204460492503130808472633361816 x 10‍−‍16. 218 | */ 219 | readonly EPSILON: number; 220 | 221 | /** 222 | * Returns true if passed value is finite. 223 | * Unlike the global isFinite, Number.isFinite doesn't forcibly convert the parameter to a 224 | * number. Only finite values of the type number, result in true. 225 | * @param number A numeric value. 226 | */ 227 | isFinite(number: number): boolean; 228 | 229 | /** 230 | * Returns true if the value passed is an integer, false otherwise. 231 | * @param number A numeric value. 232 | */ 233 | isInteger(number: number): boolean; 234 | 235 | /** 236 | * Returns a Boolean value that indicates whether a value is the reserved value NaN (not a 237 | * number). Unlike the global isNaN(), Number.isNaN() doesn't forcefully convert the parameter 238 | * to a number. Only values of the type number, that are also NaN, result in true. 239 | * @param number A numeric value. 240 | */ 241 | isNaN(number: number): boolean; 242 | 243 | /** 244 | * Returns true if the value passed is a safe integer. 245 | * @param number A numeric value. 246 | */ 247 | isSafeInteger(number: number): boolean; 248 | 249 | /** 250 | * The value of the largest integer n such that n and n + 1 are both exactly representable as 251 | * a Number value. 252 | * The value of Number.MAX_SAFE_INTEGER is 9007199254740991 2^53 − 1. 253 | */ 254 | readonly MAX_SAFE_INTEGER: number; 255 | 256 | /** 257 | * The value of the smallest integer n such that n and n − 1 are both exactly representable as 258 | * a Number value. 259 | * The value of Number.MIN_SAFE_INTEGER is −9007199254740991 (−(2^53 − 1)). 260 | */ 261 | readonly MIN_SAFE_INTEGER: number; 262 | 263 | /** 264 | * Converts a string to a floating-point number. 265 | * @param string A string that contains a floating-point number. 266 | */ 267 | parseFloat(string: string): number; 268 | 269 | /** 270 | * Converts A string to an integer. 271 | * @param s A string to convert into a number. 272 | * @param radix A value between 2 and 36 that specifies the base of the number in numString. 273 | * If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. 274 | * All other strings are considered decimal. 275 | */ 276 | parseInt(string: string, radix?: number): number; 277 | } 278 | 279 | interface ObjectConstructor { 280 | /** 281 | * Copy the values of all of the enumerable own properties from one or more source objects to a 282 | * target object. Returns the target object. 283 | * @param target The target object to copy to. 284 | * @param source The source object from which to copy properties. 285 | */ 286 | assign(target: T, source: U): T & U; 287 | 288 | /** 289 | * Copy the values of all of the enumerable own properties from one or more source objects to a 290 | * target object. Returns the target object. 291 | * @param target The target object to copy to. 292 | * @param source1 The first source object from which to copy properties. 293 | * @param source2 The second source object from which to copy properties. 294 | */ 295 | assign(target: T, source1: U, source2: V): T & U & V; 296 | 297 | /** 298 | * Copy the values of all of the enumerable own properties from one or more source objects to a 299 | * target object. Returns the target object. 300 | * @param target The target object to copy to. 301 | * @param source1 The first source object from which to copy properties. 302 | * @param source2 The second source object from which to copy properties. 303 | * @param source3 The third source object from which to copy properties. 304 | */ 305 | assign(target: T, source1: U, source2: V, source3: W): T & U & V & W; 306 | 307 | /** 308 | * Copy the values of all of the enumerable own properties from one or more source objects to a 309 | * target object. Returns the target object. 310 | * @param target The target object to copy to. 311 | * @param sources One or more source objects from which to copy properties 312 | */ 313 | assign(target: object, ...sources: any[]): any; 314 | 315 | /** 316 | * Returns an array of all symbol properties found directly on object o. 317 | * @param o Object to retrieve the symbols from. 318 | */ 319 | getOwnPropertySymbols(o: any): symbol[]; 320 | 321 | /** 322 | * Returns true if the values are the same value, false otherwise. 323 | * @param value1 The first value. 324 | * @param value2 The second value. 325 | */ 326 | is(value1: any, value2: any): boolean; 327 | 328 | /** 329 | * Sets the prototype of a specified object o to object proto or null. Returns the object o. 330 | * @param o The object to change its prototype. 331 | * @param proto The value of the new prototype or null. 332 | */ 333 | setPrototypeOf(o: any, proto: object | null): any; 334 | } 335 | 336 | interface ReadonlyArray { 337 | /** 338 | * Returns the value of the first element in the array where predicate is true, and undefined 339 | * otherwise. 340 | * @param predicate find calls predicate once for each element of the array, in ascending 341 | * order, until it finds one where predicate returns true. If such an element is found, find 342 | * immediately returns that element value. Otherwise, find returns undefined. 343 | * @param thisArg If provided, it will be used as the this value for each invocation of 344 | * predicate. If it is not provided, undefined is used instead. 345 | */ 346 | find(predicate: (this: void, value: T, index: number, obj: ReadonlyArray) => value is S, thisArg?: any): S | undefined; 347 | find(predicate: (value: T, index: number, obj: ReadonlyArray) => boolean, thisArg?: any): T | undefined; 348 | 349 | /** 350 | * Returns the index of the first element in the array where predicate is true, and -1 351 | * otherwise. 352 | * @param predicate find calls predicate once for each element of the array, in ascending 353 | * order, until it finds one where predicate returns true. If such an element is found, 354 | * findIndex immediately returns that element index. Otherwise, findIndex returns -1. 355 | * @param thisArg If provided, it will be used as the this value for each invocation of 356 | * predicate. If it is not provided, undefined is used instead. 357 | */ 358 | findIndex(predicate: (value: T, index: number, obj: ReadonlyArray) => boolean, thisArg?: any): number; 359 | } 360 | 361 | interface RegExp { 362 | /** 363 | * Returns a string indicating the flags of the regular expression in question. This field is read-only. 364 | * The characters in this string are sequenced and concatenated in the following order: 365 | * 366 | * - "g" for global 367 | * - "i" for ignoreCase 368 | * - "m" for multiline 369 | * - "u" for unicode 370 | * - "y" for sticky 371 | * 372 | * If no flags are set, the value is the empty string. 373 | */ 374 | readonly flags: string; 375 | 376 | /** 377 | * Returns a Boolean value indicating the state of the sticky flag (y) used with a regular 378 | * expression. Default is false. Read-only. 379 | */ 380 | readonly sticky: boolean; 381 | 382 | /** 383 | * Returns a Boolean value indicating the state of the Unicode flag (u) used with a regular 384 | * expression. Default is false. Read-only. 385 | */ 386 | readonly unicode: boolean; 387 | } 388 | 389 | interface RegExpConstructor { 390 | new (pattern: RegExp, flags?: string): RegExp; 391 | (pattern: RegExp, flags?: string): RegExp; 392 | } 393 | 394 | interface String { 395 | /** 396 | * Returns a nonnegative integer Number less than 1114112 (0x110000) that is the code point 397 | * value of the UTF-16 encoded code point starting at the string element at position pos in 398 | * the String resulting from converting this object to a String. 399 | * If there is no element at that position, the result is undefined. 400 | * If a valid UTF-16 surrogate pair does not begin at pos, the result is the code unit at pos. 401 | */ 402 | codePointAt(pos: number): number | undefined; 403 | 404 | /** 405 | * Returns true if searchString appears as a substring of the result of converting this 406 | * object to a String, at one or more positions that are 407 | * greater than or equal to position; otherwise, returns false. 408 | * @param searchString search string 409 | * @param position If position is undefined, 0 is assumed, so as to search all of the String. 410 | */ 411 | includes(searchString: string, position?: number): boolean; 412 | 413 | /** 414 | * Returns true if the sequence of elements of searchString converted to a String is the 415 | * same as the corresponding elements of this object (converted to a String) starting at 416 | * endPosition – length(this). Otherwise returns false. 417 | */ 418 | endsWith(searchString: string, endPosition?: number): boolean; 419 | 420 | /** 421 | * Returns the String value result of normalizing the string into the normalization form 422 | * named by form as specified in Unicode Standard Annex #15, Unicode Normalization Forms. 423 | * @param form Applicable values: "NFC", "NFD", "NFKC", or "NFKD", If not specified default 424 | * is "NFC" 425 | */ 426 | normalize(form: "NFC" | "NFD" | "NFKC" | "NFKD"): string; 427 | 428 | /** 429 | * Returns the String value result of normalizing the string into the normalization form 430 | * named by form as specified in Unicode Standard Annex #15, Unicode Normalization Forms. 431 | * @param form Applicable values: "NFC", "NFD", "NFKC", or "NFKD", If not specified default 432 | * is "NFC" 433 | */ 434 | normalize(form?: string): string; 435 | 436 | /** 437 | * Returns a String value that is made from count copies appended together. If count is 0, 438 | * the empty string is returned. 439 | * @param count number of copies to append 440 | */ 441 | repeat(count: number): string; 442 | 443 | /** 444 | * Returns true if the sequence of elements of searchString converted to a String is the 445 | * same as the corresponding elements of this object (converted to a String) starting at 446 | * position. Otherwise returns false. 447 | */ 448 | startsWith(searchString: string, position?: number): boolean; 449 | 450 | /** 451 | * Returns an HTML anchor element and sets the name attribute to the text value 452 | * @param name 453 | */ 454 | anchor(name: string): string; 455 | 456 | /** Returns a HTML element */ 457 | big(): string; 458 | 459 | /** Returns a HTML element */ 460 | blink(): string; 461 | 462 | /** Returns a HTML element */ 463 | bold(): string; 464 | 465 | /** Returns a HTML element */ 466 | fixed(): string; 467 | 468 | /** Returns a HTML element and sets the color attribute value */ 469 | fontcolor(color: string): string; 470 | 471 | /** Returns a HTML element and sets the size attribute value */ 472 | fontsize(size: number): string; 473 | 474 | /** Returns a HTML element and sets the size attribute value */ 475 | fontsize(size: string): string; 476 | 477 | /** Returns an HTML element */ 478 | italics(): string; 479 | 480 | /** Returns an HTML element and sets the href attribute value */ 481 | link(url: string): string; 482 | 483 | /** Returns a HTML element */ 484 | small(): string; 485 | 486 | /** Returns a HTML element */ 487 | strike(): string; 488 | 489 | /** Returns a HTML element */ 490 | sub(): string; 491 | 492 | /** Returns a HTML element */ 493 | sup(): string; 494 | } 495 | 496 | interface StringConstructor { 497 | /** 498 | * Return the String value whose elements are, in order, the elements in the List elements. 499 | * If length is 0, the empty string is returned. 500 | */ 501 | fromCodePoint(...codePoints: number[]): string; 502 | 503 | /** 504 | * String.raw is intended for use as a tag function of a Tagged Template String. When called 505 | * as such the first argument will be a well formed template call site object and the rest 506 | * parameter will contain the substitution values. 507 | * @param template A well-formed template string call site representation. 508 | * @param substitutions A set of substitution values. 509 | */ 510 | raw(template: TemplateStringsArray, ...substitutions: any[]): string; 511 | } 512 | -------------------------------------------------------------------------------- /lib/lib.es2015.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 | /// 24 | /// 25 | /// 26 | /// 27 | /// 28 | /// 29 | /// 30 | /// 31 | -------------------------------------------------------------------------------- /lib/lib.es2015.generator.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 Generator extends Iterator { } 22 | 23 | interface GeneratorFunction { 24 | /** 25 | * Creates a new Generator object. 26 | * @param args A list of arguments the function accepts. 27 | */ 28 | new (...args: any[]): Generator; 29 | /** 30 | * Creates a new Generator object. 31 | * @param args A list of arguments the function accepts. 32 | */ 33 | (...args: any[]): Generator; 34 | /** 35 | * The length of the arguments. 36 | */ 37 | readonly length: number; 38 | /** 39 | * Returns the name of the function. 40 | */ 41 | readonly name: string; 42 | /** 43 | * A reference to the prototype. 44 | */ 45 | readonly prototype: Generator; 46 | } 47 | 48 | interface GeneratorFunctionConstructor { 49 | /** 50 | * Creates a new Generator function. 51 | * @param args A list of arguments the function accepts. 52 | */ 53 | new (...args: string[]): GeneratorFunction; 54 | /** 55 | * Creates a new Generator function. 56 | * @param args A list of arguments the function accepts. 57 | */ 58 | (...args: string[]): GeneratorFunction; 59 | /** 60 | * The length of the arguments. 61 | */ 62 | readonly length: number; 63 | /** 64 | * Returns the name of the function. 65 | */ 66 | readonly name: string; 67 | /** 68 | * A reference to the prototype. 69 | */ 70 | readonly prototype: GeneratorFunction; 71 | } 72 | -------------------------------------------------------------------------------- /lib/lib.es2015.iterable.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 | interface SymbolConstructor { 24 | /** 25 | * A method that returns the default iterator for an object. Called by the semantics of the 26 | * for-of statement. 27 | */ 28 | readonly iterator: symbol; 29 | } 30 | 31 | interface IteratorResult { 32 | done: boolean; 33 | value: T; 34 | } 35 | 36 | interface Iterator { 37 | next(value?: any): IteratorResult; 38 | return?(value?: any): IteratorResult; 39 | throw?(e?: any): IteratorResult; 40 | } 41 | 42 | interface Iterable { 43 | [Symbol.iterator](): Iterator; 44 | } 45 | 46 | interface IterableIterator extends Iterator { 47 | [Symbol.iterator](): IterableIterator; 48 | } 49 | 50 | interface Array { 51 | /** Iterator */ 52 | [Symbol.iterator](): IterableIterator; 53 | 54 | /** 55 | * Returns an iterable of key, value pairs for every entry in the array 56 | */ 57 | entries(): IterableIterator<[number, T]>; 58 | 59 | /** 60 | * Returns an iterable of keys in the array 61 | */ 62 | keys(): IterableIterator; 63 | 64 | /** 65 | * Returns an iterable of values in the array 66 | */ 67 | values(): IterableIterator; 68 | } 69 | 70 | interface ArrayConstructor { 71 | /** 72 | * Creates an array from an iterable object. 73 | * @param iterable An iterable object to convert to an array. 74 | */ 75 | from(iterable: Iterable | ArrayLike): T[]; 76 | 77 | /** 78 | * Creates an array from an iterable object. 79 | * @param iterable An iterable object to convert to an array. 80 | * @param mapfn A mapping function to call on every element of the array. 81 | * @param thisArg Value of 'this' used to invoke the mapfn. 82 | */ 83 | from(iterable: Iterable | ArrayLike, mapfn: (v: T, k: number) => U, thisArg?: any): U[]; 84 | } 85 | 86 | interface ReadonlyArray { 87 | /** Iterator of values in the array. */ 88 | [Symbol.iterator](): IterableIterator; 89 | 90 | /** 91 | * Returns an iterable of key, value pairs for every entry in the array 92 | */ 93 | entries(): IterableIterator<[number, T]>; 94 | 95 | /** 96 | * Returns an iterable of keys in the array 97 | */ 98 | keys(): IterableIterator; 99 | 100 | /** 101 | * Returns an iterable of values in the array 102 | */ 103 | values(): IterableIterator; 104 | } 105 | 106 | interface IArguments { 107 | /** Iterator */ 108 | [Symbol.iterator](): IterableIterator; 109 | } 110 | 111 | interface Map { 112 | /** Returns an iterable of entries in the map. */ 113 | [Symbol.iterator](): IterableIterator<[K, V]>; 114 | 115 | /** 116 | * Returns an iterable of key, value pairs for every entry in the map. 117 | */ 118 | entries(): IterableIterator<[K, V]>; 119 | 120 | /** 121 | * Returns an iterable of keys in the map 122 | */ 123 | keys(): IterableIterator; 124 | 125 | /** 126 | * Returns an iterable of values in the map 127 | */ 128 | values(): IterableIterator; 129 | } 130 | 131 | interface ReadonlyMap { 132 | /** Returns an iterable of entries in the map. */ 133 | [Symbol.iterator](): IterableIterator<[K, V]>; 134 | 135 | /** 136 | * Returns an iterable of key, value pairs for every entry in the map. 137 | */ 138 | entries(): IterableIterator<[K, V]>; 139 | 140 | /** 141 | * Returns an iterable of keys in the map 142 | */ 143 | keys(): IterableIterator; 144 | 145 | /** 146 | * Returns an iterable of values in the map 147 | */ 148 | values(): IterableIterator; 149 | } 150 | 151 | interface MapConstructor { 152 | new (iterable: Iterable<[K, V]>): Map; 153 | } 154 | 155 | interface WeakMap { } 156 | 157 | interface WeakMapConstructor { 158 | new (iterable: Iterable<[K, V]>): WeakMap; 159 | } 160 | 161 | interface Set { 162 | /** Iterates over values in the set. */ 163 | [Symbol.iterator](): IterableIterator; 164 | /** 165 | * Returns an iterable of [v,v] pairs for every value `v` in the set. 166 | */ 167 | entries(): IterableIterator<[T, T]>; 168 | /** 169 | * Despite its name, returns an iterable of the values in the set, 170 | */ 171 | keys(): IterableIterator; 172 | 173 | /** 174 | * Returns an iterable of values in the set. 175 | */ 176 | values(): IterableIterator; 177 | } 178 | 179 | interface ReadonlySet { 180 | /** Iterates over values in the set. */ 181 | [Symbol.iterator](): IterableIterator; 182 | 183 | /** 184 | * Returns an iterable of [v,v] pairs for every value `v` in the set. 185 | */ 186 | entries(): IterableIterator<[T, T]>; 187 | 188 | /** 189 | * Despite its name, returns an iterable of the values in the set, 190 | */ 191 | keys(): IterableIterator; 192 | 193 | /** 194 | * Returns an iterable of values in the set. 195 | */ 196 | values(): IterableIterator; 197 | } 198 | 199 | interface SetConstructor { 200 | new (iterable: Iterable): Set; 201 | } 202 | 203 | interface WeakSet { } 204 | 205 | interface WeakSetConstructor { 206 | new (iterable: Iterable): WeakSet; 207 | } 208 | 209 | interface Promise { } 210 | 211 | interface PromiseConstructor { 212 | /** 213 | * Creates a Promise that is resolved with an array of results when all of the provided Promises 214 | * resolve, or rejected when any Promise is rejected. 215 | * @param values An array of Promises. 216 | * @returns A new Promise. 217 | */ 218 | all(values: Iterable>): Promise; 219 | 220 | /** 221 | * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved 222 | * or rejected. 223 | * @param values An array of Promises. 224 | * @returns A new Promise. 225 | */ 226 | race(values: Iterable>): Promise; 227 | } 228 | 229 | declare namespace Reflect { 230 | function enumerate(target: object): IterableIterator; 231 | } 232 | 233 | interface String { 234 | /** Iterator */ 235 | [Symbol.iterator](): IterableIterator; 236 | } 237 | 238 | interface Int8Array { 239 | [Symbol.iterator](): IterableIterator; 240 | /** 241 | * Returns an array of key, value pairs for every entry in the array 242 | */ 243 | entries(): IterableIterator<[number, number]>; 244 | /** 245 | * Returns an list of keys in the array 246 | */ 247 | keys(): IterableIterator; 248 | /** 249 | * Returns an list of values in the array 250 | */ 251 | values(): IterableIterator; 252 | } 253 | 254 | interface Int8ArrayConstructor { 255 | new (elements: Iterable): Int8Array; 256 | 257 | /** 258 | * Creates an array from an array-like or iterable object. 259 | * @param arrayLike An array-like or iterable object to convert to an array. 260 | * @param mapfn A mapping function to call on every element of the array. 261 | * @param thisArg Value of 'this' used to invoke the mapfn. 262 | */ 263 | from(arrayLike: Iterable, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array; 264 | } 265 | 266 | interface Uint8Array { 267 | [Symbol.iterator](): IterableIterator; 268 | /** 269 | * Returns an array of key, value pairs for every entry in the array 270 | */ 271 | entries(): IterableIterator<[number, number]>; 272 | /** 273 | * Returns an list of keys in the array 274 | */ 275 | keys(): IterableIterator; 276 | /** 277 | * Returns an list of values in the array 278 | */ 279 | values(): IterableIterator; 280 | } 281 | 282 | interface Uint8ArrayConstructor { 283 | new (elements: Iterable): Uint8Array; 284 | 285 | /** 286 | * Creates an array from an array-like or iterable object. 287 | * @param arrayLike An array-like or iterable object to convert to an array. 288 | * @param mapfn A mapping function to call on every element of the array. 289 | * @param thisArg Value of 'this' used to invoke the mapfn. 290 | */ 291 | from(arrayLike: Iterable, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8Array; 292 | } 293 | 294 | interface Uint8ClampedArray { 295 | [Symbol.iterator](): IterableIterator; 296 | /** 297 | * Returns an array of key, value pairs for every entry in the array 298 | */ 299 | entries(): IterableIterator<[number, number]>; 300 | 301 | /** 302 | * Returns an list of keys in the array 303 | */ 304 | keys(): IterableIterator; 305 | 306 | /** 307 | * Returns an list of values in the array 308 | */ 309 | values(): IterableIterator; 310 | } 311 | 312 | interface Uint8ClampedArrayConstructor { 313 | new (elements: Iterable): Uint8ClampedArray; 314 | 315 | 316 | /** 317 | * Creates an array from an array-like or iterable object. 318 | * @param arrayLike An array-like or iterable object to convert to an array. 319 | * @param mapfn A mapping function to call on every element of the array. 320 | * @param thisArg Value of 'this' used to invoke the mapfn. 321 | */ 322 | from(arrayLike: Iterable, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8ClampedArray; 323 | } 324 | 325 | interface Int16Array { 326 | [Symbol.iterator](): IterableIterator; 327 | /** 328 | * Returns an array of key, value pairs for every entry in the array 329 | */ 330 | entries(): IterableIterator<[number, number]>; 331 | 332 | /** 333 | * Returns an list of keys in the array 334 | */ 335 | keys(): IterableIterator; 336 | 337 | /** 338 | * Returns an list of values in the array 339 | */ 340 | values(): IterableIterator; 341 | } 342 | 343 | interface Int16ArrayConstructor { 344 | new (elements: Iterable): Int16Array; 345 | 346 | /** 347 | * Creates an array from an array-like or iterable object. 348 | * @param arrayLike An array-like or iterable object to convert to an array. 349 | * @param mapfn A mapping function to call on every element of the array. 350 | * @param thisArg Value of 'this' used to invoke the mapfn. 351 | */ 352 | from(arrayLike: Iterable, mapfn?: (v: number, k: number) => number, thisArg?: any): Int16Array; 353 | } 354 | 355 | interface Uint16Array { 356 | [Symbol.iterator](): IterableIterator; 357 | /** 358 | * Returns an array of key, value pairs for every entry in the array 359 | */ 360 | entries(): IterableIterator<[number, number]>; 361 | /** 362 | * Returns an list of keys in the array 363 | */ 364 | keys(): IterableIterator; 365 | /** 366 | * Returns an list of values in the array 367 | */ 368 | values(): IterableIterator; 369 | } 370 | 371 | interface Uint16ArrayConstructor { 372 | new (elements: Iterable): Uint16Array; 373 | 374 | /** 375 | * Creates an array from an array-like or iterable object. 376 | * @param arrayLike An array-like or iterable object to convert to an array. 377 | * @param mapfn A mapping function to call on every element of the array. 378 | * @param thisArg Value of 'this' used to invoke the mapfn. 379 | */ 380 | from(arrayLike: Iterable, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint16Array; 381 | } 382 | 383 | interface Int32Array { 384 | [Symbol.iterator](): IterableIterator; 385 | /** 386 | * Returns an array of key, value pairs for every entry in the array 387 | */ 388 | entries(): IterableIterator<[number, number]>; 389 | /** 390 | * Returns an list of keys in the array 391 | */ 392 | keys(): IterableIterator; 393 | /** 394 | * Returns an list of values in the array 395 | */ 396 | values(): IterableIterator; 397 | } 398 | 399 | interface Int32ArrayConstructor { 400 | new (elements: Iterable): Int32Array; 401 | 402 | /** 403 | * Creates an array from an array-like or iterable object. 404 | * @param arrayLike An array-like or iterable object to convert to an array. 405 | * @param mapfn A mapping function to call on every element of the array. 406 | * @param thisArg Value of 'this' used to invoke the mapfn. 407 | */ 408 | from(arrayLike: Iterable, mapfn?: (v: number, k: number) => number, thisArg?: any): Int32Array; 409 | } 410 | 411 | interface Uint32Array { 412 | [Symbol.iterator](): IterableIterator; 413 | /** 414 | * Returns an array of key, value pairs for every entry in the array 415 | */ 416 | entries(): IterableIterator<[number, number]>; 417 | /** 418 | * Returns an list of keys in the array 419 | */ 420 | keys(): IterableIterator; 421 | /** 422 | * Returns an list of values in the array 423 | */ 424 | values(): IterableIterator; 425 | } 426 | 427 | interface Uint32ArrayConstructor { 428 | new (elements: Iterable): Uint32Array; 429 | 430 | /** 431 | * Creates an array from an array-like or iterable object. 432 | * @param arrayLike An array-like or iterable object to convert to an array. 433 | * @param mapfn A mapping function to call on every element of the array. 434 | * @param thisArg Value of 'this' used to invoke the mapfn. 435 | */ 436 | from(arrayLike: Iterable, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint32Array; 437 | } 438 | 439 | interface Float32Array { 440 | [Symbol.iterator](): IterableIterator; 441 | /** 442 | * Returns an array of key, value pairs for every entry in the array 443 | */ 444 | entries(): IterableIterator<[number, number]>; 445 | /** 446 | * Returns an list of keys in the array 447 | */ 448 | keys(): IterableIterator; 449 | /** 450 | * Returns an list of values in the array 451 | */ 452 | values(): IterableIterator; 453 | } 454 | 455 | interface Float32ArrayConstructor { 456 | new (elements: Iterable): Float32Array; 457 | 458 | /** 459 | * Creates an array from an array-like or iterable object. 460 | * @param arrayLike An array-like or iterable object to convert to an array. 461 | * @param mapfn A mapping function to call on every element of the array. 462 | * @param thisArg Value of 'this' used to invoke the mapfn. 463 | */ 464 | from(arrayLike: Iterable, mapfn?: (v: number, k: number) => number, thisArg?: any): Float32Array; 465 | } 466 | 467 | interface Float64Array { 468 | [Symbol.iterator](): IterableIterator; 469 | /** 470 | * Returns an array of key, value pairs for every entry in the array 471 | */ 472 | entries(): IterableIterator<[number, number]>; 473 | /** 474 | * Returns an list of keys in the array 475 | */ 476 | keys(): IterableIterator; 477 | /** 478 | * Returns an list of values in the array 479 | */ 480 | values(): IterableIterator; 481 | } 482 | 483 | interface Float64ArrayConstructor { 484 | new (elements: Iterable): Float64Array; 485 | 486 | /** 487 | * Creates an array from an array-like or iterable object. 488 | * @param arrayLike An array-like or iterable object to convert to an array. 489 | * @param mapfn A mapping function to call on every element of the array. 490 | * @param thisArg Value of 'this' used to invoke the mapfn. 491 | */ 492 | from(arrayLike: Iterable, mapfn?: (v: number, k: number) => number, thisArg?: any): Float64Array; 493 | } 494 | -------------------------------------------------------------------------------- /lib/lib.es2015.promise.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 PromiseConstructor { 22 | /** 23 | * A reference to the prototype. 24 | */ 25 | readonly prototype: Promise; 26 | 27 | /** 28 | * Creates a new Promise. 29 | * @param executor A callback used to initialize the promise. This callback is passed two arguments: 30 | * a resolve callback used to resolve the promise with a value or the result of another promise, 31 | * and a reject callback used to reject the promise with a provided reason or error. 32 | */ 33 | new (executor: (resolve: (value?: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; 34 | 35 | /** 36 | * Creates a Promise that is resolved with an array of results when all of the provided Promises 37 | * resolve, or rejected when any Promise is rejected. 38 | * @param values An array of Promises. 39 | * @returns A new Promise. 40 | */ 41 | all(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike , T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike, T10 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; 42 | 43 | /** 44 | * Creates a Promise that is resolved with an array of results when all of the provided Promises 45 | * resolve, or rejected when any Promise is rejected. 46 | * @param values An array of Promises. 47 | * @returns A new Promise. 48 | */ 49 | all(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike , T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; 50 | 51 | /** 52 | * Creates a Promise that is resolved with an array of results when all of the provided Promises 53 | * resolve, or rejected when any Promise is rejected. 54 | * @param values An array of Promises. 55 | * @returns A new Promise. 56 | */ 57 | all(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike , T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; 58 | 59 | /** 60 | * Creates a Promise that is resolved with an array of results when all of the provided Promises 61 | * resolve, or rejected when any Promise is rejected. 62 | * @param values An array of Promises. 63 | * @returns A new Promise. 64 | */ 65 | all(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike , T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; 66 | 67 | /** 68 | * Creates a Promise that is resolved with an array of results when all of the provided Promises 69 | * resolve, or rejected when any Promise is rejected. 70 | * @param values An array of Promises. 71 | * @returns A new Promise. 72 | */ 73 | all(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike , T5 | PromiseLike, T6 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6]>; 74 | 75 | /** 76 | * Creates a Promise that is resolved with an array of results when all of the provided Promises 77 | * resolve, or rejected when any Promise is rejected. 78 | * @param values An array of Promises. 79 | * @returns A new Promise. 80 | */ 81 | all(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike , T5 | PromiseLike]): Promise<[T1, T2, T3, T4, T5]>; 82 | 83 | /** 84 | * Creates a Promise that is resolved with an array of results when all of the provided Promises 85 | * resolve, or rejected when any Promise is rejected. 86 | * @param values An array of Promises. 87 | * @returns A new Promise. 88 | */ 89 | all(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike ]): Promise<[T1, T2, T3, T4]>; 90 | 91 | /** 92 | * Creates a Promise that is resolved with an array of results when all of the provided Promises 93 | * resolve, or rejected when any Promise is rejected. 94 | * @param values An array of Promises. 95 | * @returns A new Promise. 96 | */ 97 | all(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike]): Promise<[T1, T2, T3]>; 98 | 99 | /** 100 | * Creates a Promise that is resolved with an array of results when all of the provided Promises 101 | * resolve, or rejected when any Promise is rejected. 102 | * @param values An array of Promises. 103 | * @returns A new Promise. 104 | */ 105 | all(values: [T1 | PromiseLike, T2 | PromiseLike]): Promise<[T1, T2]>; 106 | 107 | /** 108 | * Creates a Promise that is resolved with an array of results when all of the provided Promises 109 | * resolve, or rejected when any Promise is rejected. 110 | * @param values An array of Promises. 111 | * @returns A new Promise. 112 | */ 113 | all(values: (T | PromiseLike)[]): Promise; 114 | 115 | /** 116 | * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved 117 | * or rejected. 118 | * @param values An array of Promises. 119 | * @returns A new Promise. 120 | */ 121 | race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike, T10 | PromiseLike]): Promise; 122 | 123 | /** 124 | * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved 125 | * or rejected. 126 | * @param values An array of Promises. 127 | * @returns A new Promise. 128 | */ 129 | race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike]): Promise; 130 | 131 | /** 132 | * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved 133 | * or rejected. 134 | * @param values An array of Promises. 135 | * @returns A new Promise. 136 | */ 137 | race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike]): Promise; 138 | 139 | /** 140 | * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved 141 | * or rejected. 142 | * @param values An array of Promises. 143 | * @returns A new Promise. 144 | */ 145 | race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike]): Promise; 146 | 147 | /** 148 | * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved 149 | * or rejected. 150 | * @param values An array of Promises. 151 | * @returns A new Promise. 152 | */ 153 | race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike]): Promise; 154 | 155 | /** 156 | * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved 157 | * or rejected. 158 | * @param values An array of Promises. 159 | * @returns A new Promise. 160 | */ 161 | race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike]): Promise; 162 | 163 | /** 164 | * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved 165 | * or rejected. 166 | * @param values An array of Promises. 167 | * @returns A new Promise. 168 | */ 169 | race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike]): Promise; 170 | 171 | /** 172 | * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved 173 | * or rejected. 174 | * @param values An array of Promises. 175 | * @returns A new Promise. 176 | */ 177 | race(values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike]): Promise; 178 | 179 | /** 180 | * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved 181 | * or rejected. 182 | * @param values An array of Promises. 183 | * @returns A new Promise. 184 | */ 185 | race(values: [T1 | PromiseLike, T2 | PromiseLike]): Promise; 186 | 187 | /** 188 | * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved 189 | * or rejected. 190 | * @param values An array of Promises. 191 | * @returns A new Promise. 192 | */ 193 | race(values: (T | PromiseLike)[]): Promise; 194 | 195 | /** 196 | * Creates a new rejected promise for the provided reason. 197 | * @param reason The reason the promise was rejected. 198 | * @returns A new rejected Promise. 199 | */ 200 | reject(reason?: any): Promise; 201 | 202 | /** 203 | * Creates a new resolved promise for the provided value. 204 | * @param value A promise. 205 | * @returns A promise whose internal state matches the provided promise. 206 | */ 207 | resolve(value: T | PromiseLike): Promise; 208 | 209 | /** 210 | * Creates a new resolved promise . 211 | * @returns A resolved promise. 212 | */ 213 | resolve(): Promise; 214 | } 215 | 216 | declare var Promise: PromiseConstructor; 217 | -------------------------------------------------------------------------------- /lib/lib.es2015.proxy.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 ProxyHandler { 22 | getPrototypeOf? (target: T): object | null; 23 | setPrototypeOf? (target: T, v: any): boolean; 24 | isExtensible? (target: T): boolean; 25 | preventExtensions? (target: T): boolean; 26 | getOwnPropertyDescriptor? (target: T, p: PropertyKey): PropertyDescriptor | undefined; 27 | has? (target: T, p: PropertyKey): boolean; 28 | get? (target: T, p: PropertyKey, receiver: any): any; 29 | set? (target: T, p: PropertyKey, value: any, receiver: any): boolean; 30 | deleteProperty? (target: T, p: PropertyKey): boolean; 31 | defineProperty? (target: T, p: PropertyKey, attributes: PropertyDescriptor): boolean; 32 | enumerate? (target: T): PropertyKey[]; 33 | ownKeys? (target: T): PropertyKey[]; 34 | apply? (target: T, thisArg: any, argArray?: any): any; 35 | construct? (target: T, argArray: any, newTarget?: any): object; 36 | } 37 | 38 | interface ProxyConstructor { 39 | revocable(target: T, handler: ProxyHandler): { proxy: T; revoke: () => void; }; 40 | new (target: T, handler: ProxyHandler): T; 41 | } 42 | declare var Proxy: ProxyConstructor; 43 | -------------------------------------------------------------------------------- /lib/lib.es2015.reflect.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 | declare namespace Reflect { 22 | function apply(target: Function, thisArgument: any, argumentsList: ArrayLike): any; 23 | function construct(target: Function, argumentsList: ArrayLike, newTarget?: any): any; 24 | function defineProperty(target: object, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean; 25 | function deleteProperty(target: object, propertyKey: PropertyKey): boolean; 26 | function get(target: object, propertyKey: PropertyKey, receiver?: any): any; 27 | function getOwnPropertyDescriptor(target: object, propertyKey: PropertyKey): PropertyDescriptor | undefined; 28 | function getPrototypeOf(target: object): object; 29 | function has(target: object, propertyKey: PropertyKey): boolean; 30 | function isExtensible(target: object): boolean; 31 | function ownKeys(target: object): PropertyKey[]; 32 | function preventExtensions(target: object): boolean; 33 | function set(target: object, propertyKey: PropertyKey, value: any, receiver?: any): boolean; 34 | function setPrototypeOf(target: object, proto: any): boolean; 35 | } 36 | -------------------------------------------------------------------------------- /lib/lib.es2015.symbol.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 SymbolConstructor { 22 | /** 23 | * A reference to the prototype. 24 | */ 25 | readonly prototype: Symbol; 26 | 27 | /** 28 | * Returns a new unique Symbol value. 29 | * @param description Description of the new Symbol object. 30 | */ 31 | (description?: string | number): symbol; 32 | 33 | /** 34 | * Returns a Symbol object from the global symbol registry matching the given key if found. 35 | * Otherwise, returns a new symbol with this key. 36 | * @param key key to search for. 37 | */ 38 | for(key: string): symbol; 39 | 40 | /** 41 | * Returns a key from the global symbol registry matching the given Symbol if found. 42 | * Otherwise, returns a undefined. 43 | * @param sym Symbol to find the key for. 44 | */ 45 | keyFor(sym: symbol): string | undefined; 46 | } 47 | 48 | declare var Symbol: SymbolConstructor; -------------------------------------------------------------------------------- /lib/lib.es2015.symbol.wellknown.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 | interface SymbolConstructor { 24 | /** 25 | * A method that determines if a constructor object recognizes an object as one of the 26 | * constructor’s instances. Called by the semantics of the instanceof operator. 27 | */ 28 | readonly hasInstance: symbol; 29 | 30 | /** 31 | * A Boolean value that if true indicates that an object should flatten to its array elements 32 | * by Array.prototype.concat. 33 | */ 34 | readonly isConcatSpreadable: symbol; 35 | 36 | /** 37 | * A regular expression method that matches the regular expression against a string. Called 38 | * by the String.prototype.match method. 39 | */ 40 | readonly match: symbol; 41 | 42 | /** 43 | * A regular expression method that replaces matched substrings of a string. Called by the 44 | * String.prototype.replace method. 45 | */ 46 | readonly replace: symbol; 47 | 48 | /** 49 | * A regular expression method that returns the index within a string that matches the 50 | * regular expression. Called by the String.prototype.search method. 51 | */ 52 | readonly search: symbol; 53 | 54 | /** 55 | * A function valued property that is the constructor function that is used to create 56 | * derived objects. 57 | */ 58 | readonly species: symbol; 59 | 60 | /** 61 | * A regular expression method that splits a string at the indices that match the regular 62 | * expression. Called by the String.prototype.split method. 63 | */ 64 | readonly split: symbol; 65 | 66 | /** 67 | * A method that converts an object to a corresponding primitive value. 68 | * Called by the ToPrimitive abstract operation. 69 | */ 70 | readonly toPrimitive: symbol; 71 | 72 | /** 73 | * A String value that is used in the creation of the default string description of an object. 74 | * Called by the built-in method Object.prototype.toString. 75 | */ 76 | readonly toStringTag: symbol; 77 | 78 | /** 79 | * An Object whose own property names are property names that are excluded from the 'with' 80 | * environment bindings of the associated objects. 81 | */ 82 | readonly unscopables: symbol; 83 | } 84 | 85 | interface Symbol { 86 | readonly [Symbol.toStringTag]: string; 87 | } 88 | 89 | interface Array { 90 | /** 91 | * Returns an object whose properties have the value 'true' 92 | * when they will be absent when used in a 'with' statement. 93 | */ 94 | [Symbol.unscopables](): { 95 | copyWithin: boolean; 96 | entries: boolean; 97 | fill: boolean; 98 | find: boolean; 99 | findIndex: boolean; 100 | keys: boolean; 101 | values: boolean; 102 | }; 103 | } 104 | 105 | interface Date { 106 | /** 107 | * Converts a Date object to a string. 108 | */ 109 | [Symbol.toPrimitive](hint: "default"): string; 110 | /** 111 | * Converts a Date object to a string. 112 | */ 113 | [Symbol.toPrimitive](hint: "string"): string; 114 | /** 115 | * Converts a Date object to a number. 116 | */ 117 | [Symbol.toPrimitive](hint: "number"): number; 118 | /** 119 | * Converts a Date object to a string or number. 120 | * 121 | * @param hint The strings "number", "string", or "default" to specify what primitive to return. 122 | * 123 | * @throws {TypeError} If 'hint' was given something other than "number", "string", or "default". 124 | * @returns A number if 'hint' was "number", a string if 'hint' was "string" or "default". 125 | */ 126 | [Symbol.toPrimitive](hint: string): string | number; 127 | } 128 | 129 | interface Map { 130 | readonly [Symbol.toStringTag]: string; 131 | } 132 | 133 | interface WeakMap { 134 | readonly [Symbol.toStringTag]: string; 135 | } 136 | 137 | interface Set { 138 | readonly [Symbol.toStringTag]: string; 139 | } 140 | 141 | interface WeakSet { 142 | readonly [Symbol.toStringTag]: string; 143 | } 144 | 145 | interface JSON { 146 | readonly [Symbol.toStringTag]: string; 147 | } 148 | 149 | interface Function { 150 | /** 151 | * Determines whether the given value inherits from this function if this function was used 152 | * as a constructor function. 153 | * 154 | * A constructor function can control which objects are recognized as its instances by 155 | * 'instanceof' by overriding this method. 156 | */ 157 | [Symbol.hasInstance](value: any): boolean; 158 | } 159 | 160 | interface GeneratorFunction { 161 | readonly [Symbol.toStringTag]: string; 162 | } 163 | 164 | interface Math { 165 | readonly [Symbol.toStringTag]: string; 166 | } 167 | 168 | interface Promise { 169 | readonly [Symbol.toStringTag]: string; 170 | } 171 | 172 | interface PromiseConstructor { 173 | readonly [Symbol.species]: PromiseConstructor; 174 | } 175 | 176 | interface RegExp { 177 | /** 178 | * Matches a string with this regular expression, and returns an array containing the results of 179 | * that search. 180 | * @param string A string to search within. 181 | */ 182 | [Symbol.match](string: string): RegExpMatchArray | null; 183 | 184 | /** 185 | * Replaces text in a string, using this regular expression. 186 | * @param string A String object or string literal whose contents matching against 187 | * this regular expression will be replaced 188 | * @param replaceValue A String object or string literal containing the text to replace for every 189 | * successful match of this regular expression. 190 | */ 191 | [Symbol.replace](string: string, replaceValue: string): string; 192 | 193 | /** 194 | * Replaces text in a string, using this regular expression. 195 | * @param string A String object or string literal whose contents matching against 196 | * this regular expression will be replaced 197 | * @param replacer A function that returns the replacement text. 198 | */ 199 | [Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string; 200 | 201 | /** 202 | * Finds the position beginning first substring match in a regular expression search 203 | * using this regular expression. 204 | * 205 | * @param string The string to search within. 206 | */ 207 | [Symbol.search](string: string): number; 208 | 209 | /** 210 | * Returns an array of substrings that were delimited by strings in the original input that 211 | * match against this regular expression. 212 | * 213 | * If the regular expression contains capturing parentheses, then each time this 214 | * regular expression matches, the results (including any undefined results) of the 215 | * capturing parentheses are spliced. 216 | * 217 | * @param string string value to split 218 | * @param limit if not undefined, the output array is truncated so that it contains no more 219 | * than 'limit' elements. 220 | */ 221 | [Symbol.split](string: string, limit?: number): string[]; 222 | } 223 | 224 | interface RegExpConstructor { 225 | readonly [Symbol.species]: RegExpConstructor; 226 | } 227 | 228 | interface String { 229 | /** 230 | * Matches a string an object that supports being matched against, and returns an array containing the results of that search. 231 | * @param matcher An object that supports being matched against. 232 | */ 233 | match(matcher: { [Symbol.match](string: string): RegExpMatchArray | null; }): RegExpMatchArray | null; 234 | 235 | /** 236 | * Replaces text in a string, using an object that supports replacement within a string. 237 | * @param searchValue A object can search for and replace matches within a string. 238 | * @param replaceValue A string containing the text to replace for every successful match of searchValue in this string. 239 | */ 240 | replace(searchValue: { [Symbol.replace](string: string, replaceValue: string): string; }, replaceValue: string): string; 241 | 242 | /** 243 | * Replaces text in a string, using an object that supports replacement within a string. 244 | * @param searchValue A object can search for and replace matches within a string. 245 | * @param replacer A function that returns the replacement text. 246 | */ 247 | replace(searchValue: { [Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string; }, replacer: (substring: string, ...args: any[]) => string): string; 248 | 249 | /** 250 | * Finds the first substring match in a regular expression search. 251 | * @param searcher An object which supports searching within a string. 252 | */ 253 | search(searcher: { [Symbol.search](string: string): number; }): number; 254 | 255 | /** 256 | * Split a string into substrings using the specified separator and return them as an array. 257 | * @param splitter An object that can split a string. 258 | * @param limit A value used to limit the number of elements returned in the array. 259 | */ 260 | split(splitter: { [Symbol.split](string: string, limit?: number): string[]; }, limit?: number): string[]; 261 | } 262 | 263 | interface ArrayBuffer { 264 | readonly [Symbol.toStringTag]: string; 265 | } 266 | 267 | interface DataView { 268 | readonly [Symbol.toStringTag]: string; 269 | } 270 | 271 | interface Int8Array { 272 | readonly [Symbol.toStringTag]: "Int8Array"; 273 | } 274 | 275 | interface Uint8Array { 276 | readonly [Symbol.toStringTag]: "UInt8Array"; 277 | } 278 | 279 | interface Uint8ClampedArray { 280 | readonly [Symbol.toStringTag]: "Uint8ClampedArray"; 281 | } 282 | 283 | interface Int16Array { 284 | readonly [Symbol.toStringTag]: "Int16Array"; 285 | } 286 | 287 | interface Uint16Array { 288 | readonly [Symbol.toStringTag]: "Uint16Array"; 289 | } 290 | 291 | interface Int32Array { 292 | readonly [Symbol.toStringTag]: "Int32Array"; 293 | } 294 | 295 | interface Uint32Array { 296 | readonly [Symbol.toStringTag]: "Uint32Array"; 297 | } 298 | 299 | interface Float32Array { 300 | readonly [Symbol.toStringTag]: "Float32Array"; 301 | } 302 | 303 | interface Float64Array { 304 | readonly [Symbol.toStringTag]: "Float64Array"; 305 | } 306 | 307 | interface ArrayConstructor { 308 | readonly [Symbol.species]: ArrayConstructor; 309 | } 310 | interface MapConstructor { 311 | readonly [Symbol.species]: MapConstructor; 312 | } 313 | interface SetConstructor { 314 | readonly [Symbol.species]: SetConstructor; 315 | } 316 | interface ArrayBufferConstructor { 317 | readonly [Symbol.species]: ArrayBufferConstructor; 318 | } -------------------------------------------------------------------------------- /lib/lib.typetalk.d.ts: -------------------------------------------------------------------------------- 1 | declare const globals: any; 2 | 3 | declare class TTClass { 4 | static addClass(name: string): TTClass; 5 | static getClass(name: string): TTClass|undefined; 6 | static getAllClasses(): Map; 7 | static recompile(); 8 | 9 | static subscribe(subscriber: TTClassChangeListener); 10 | 11 | prototype: any; 12 | getSource(): string; 13 | setSource(typescript: string); 14 | getCommitted(): boolean; 15 | getErrors(): ReadonlyArray; 16 | } 17 | 18 | declare class TypeTalk { 19 | } 20 | 21 | declare interface TTClassChangeListener { 22 | onClassesChanged(); 23 | } 24 | 25 | declare function nativeConstructor(theInstance: any, theClass: any, ...args: any); 26 | 27 | -------------------------------------------------------------------------------- /src/Browser.tsx: -------------------------------------------------------------------------------- 1 | class Browser extends Runnable implements TTClassChangeListener { 2 | protected ids = new class { 3 | runnables?: JsxVBox; 4 | }; 5 | private runnables = new Map Runnable>(); 6 | 7 | static title() { 8 | return "Browser"; 9 | } 10 | 11 | onClassesChanged() { 12 | let classes = TTClass.getAllClasses(); 13 | 14 | let runnables = this.ids.runnables!.root!; 15 | while (runnables.lastChild) 16 | runnables.removeChild(runnables.lastChild); 17 | 18 | let jsx = this.newJsxFactory(); 19 | for (let [className, ttclass] of classes) { 20 | if (ttclass && ttclass.prototype) { 21 | let proto = ttclass.prototype; 22 | if (proto instanceof Runnable) { 23 | let title = (ttclass as any).title; 24 | if (title) { 25 | runnables.appendChild( 26 | 29 | ); 30 | } 31 | } 32 | } 33 | } 34 | 35 | TTClass.subscribe(this); 36 | } 37 | 38 | render(jsx, props) { 39 | let children: Element[] = []; 40 | for (let [name, runnable] of this.runnables) { 41 | children.push( 42 | 43 | ); 44 | } 45 | let ui = 46 | 47 | 48 | 49 | 50 | 51 | ; 52 | this.onClassesChanged(); 53 | return ui; 54 | } 55 | 56 | private async onImportButtonClicked() { 57 | var selector = document.createElement('input'); 58 | selector.setAttribute('type', 'file'); 59 | selector.onchange = e => this.onImport(e); 60 | selector.click(); 61 | } 62 | 63 | private async onImport(e: Event) { 64 | let input = e.target as HTMLInputElement; 65 | let pd = await ProgressDialogue.run("Loading", 100); 66 | try { 67 | if (!input.files || (input.files.length != 1)) 68 | throw "You must specify exactly one file to import"; 69 | 70 | let data = await new Promise((resolve, reject) => { 71 | let reader = new FileReader(); 72 | reader.onload = () => resolve(reader.result as ArrayBuffer) 73 | reader.onerror = reject; 74 | reader.readAsArrayBuffer(input.files![0]); 75 | }); 76 | 77 | let jszip = globals.JSZip() as JSZip; 78 | await jszip.loadAsync(data, {}); 79 | 80 | let files = new Array(); 81 | jszip.forEach((name, file) => { 82 | if (name.match(/^[^/]*\.tsx$/)) { 83 | files.push(file); 84 | } 85 | }); 86 | 87 | for (let i = 0; i < files.length; i++) { 88 | let file = files[i]; 89 | let ttclass = TTClass.addClass(file.name.replace(/\.tsx$/, "")); 90 | await pd.update(100 * i / files.length); 91 | let content = await file.async("string"); 92 | ttclass.setSource(content); 93 | } 94 | await pd.update(100); 95 | TTClass.recompile(); 96 | } finally { 97 | pd.close(); 98 | } 99 | } 100 | 101 | private async onExport() { 102 | let jszip = globals.JSZip() as JSZip; 103 | let classes = TTClass.getAllClasses(); 104 | let pd = await ProgressDialogue.run("Loading", 100); 105 | try { 106 | for (let [name, ttclass] of classes) 107 | jszip.file(`${name}.tsx`, ttclass.getSource()); 108 | 109 | let data: Blob = await jszip.generateAsync( 110 | { 111 | type: "blob", 112 | compression: "DEFLATE", 113 | }, 114 | progress => pd.update(progress) 115 | ); 116 | await pd.update(100); 117 | globals.saveAs(data, "export.zip"); 118 | } finally { 119 | pd.close(); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/ClockRunnable.tsx: -------------------------------------------------------------------------------- 1 | class ClockRunnable extends Runnable { 2 | protected ids = new class { 3 | canvas?: HTMLCanvasElement; 4 | }; 5 | 6 | static title() { 7 | return "Dubious clock"; 8 | } 9 | 10 | async run() { 11 | super.run(); 12 | 13 | let ctx = this.ids.canvas!.getContext("2d")!; 14 | 15 | function sleep(ms: number) { 16 | return new Promise(resolve => window.setTimeout(resolve, ms)); 17 | } 18 | 19 | while (this.isAttached()) { 20 | this.redraw(ctx); 21 | await sleep(1000); 22 | } 23 | } 24 | 25 | private redraw(ctx) { 26 | function drawHand(angle, length) { 27 | angle -= Math.PI / 2; 28 | ctx.moveTo(100, 100); 29 | ctx.lineTo(100 + Math.cos(angle)*length, 100 + Math.sin(angle)*length); 30 | } 31 | 32 | let RADIUS = 90; 33 | ctx.strokeStyle = "#000"; 34 | ctx.fillStyle = "#ccc"; 35 | 36 | ctx.fillRect(0, 0, 200, 200); 37 | ctx.beginPath(); 38 | ctx.arc(100, 100, RADIUS, 0, 2*Math.PI); 39 | 40 | let now = new Date() 41 | drawHand(now.getSeconds() * 2*Math.PI / 60, RADIUS * 9/10); 42 | drawHand(now.getMinutes() * 2*Math.PI / 60, RADIUS * 2/3); 43 | drawHand(now.getHours() * 2*Math.PI / 24, RADIUS * 1/3); 44 | 45 | ctx.stroke(); 46 | } 47 | 48 | render(jsx, props) { 49 | return this.onClose()} 51 | title="Dubious clock"> 52 | 53 | ; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/EditorComponent.tsx: -------------------------------------------------------------------------------- 1 | class EditorComponent extends UiComponent implements TTClassChangeListener { 2 | protected ids = new class { 3 | textarea?: HTMLTextAreaElement; 4 | codemirror?: CodeMirror.EditorFromTextArea; 5 | classlist?: HTMLSelectElement; 6 | }; 7 | private currentClass?: TTClass; 8 | 9 | onClassesChanged() { 10 | let classes = TTClass.getAllClasses(); 11 | let classNames = Array.from(classes.keys()).sort(); 12 | let classlist = this.ids.classlist!; 13 | while (classlist.lastChild) 14 | classlist.removeChild(classlist.lastChild); 15 | 16 | let jsx = this.newJsxFactory(); 17 | for (let className of classNames) { 18 | let ttclass = classes.get(className)!; 19 | classlist.appendChild( 20 | 23 | ); 24 | } 25 | 26 | TTClass.subscribe(this); 27 | } 28 | 29 | private flushDirtySource() { 30 | if (this.currentClass && this.ids.codemirror) { 31 | let src = this.ids.codemirror.getValue(); 32 | this.currentClass.setSource(src); 33 | } 34 | } 35 | 36 | private onClassSelected(ttclass: TTClass) { 37 | this.flushDirtySource(); 38 | 39 | this.currentClass = ttclass; 40 | let src = ttclass.getSource(); 41 | let cm = this.ids.codemirror!; 42 | cm.setValue(src); 43 | 44 | let jsx = this.newJsxFactory(); 45 | for (let e of ttclass.getErrors()) { 46 | let pos = e.file!.getLineAndCharacterOfPosition(e.start!); 47 | let text = ts.flattenDiagnosticMessageText(e.messageText, "\n"); 48 | cm.addLineWidget(pos.line,
{text}
); 49 | } 50 | } 51 | 52 | private onCommit() { 53 | this.flushDirtySource(); 54 | TTClass.recompile(); 55 | this.onClassSelected(this.currentClass!); 56 | } 57 | 58 | private async onNewClass() { 59 | let className = await QueryDialogue.run("New class name", 60 | "What do you want to call your new class?"); 61 | if (!className) 62 | return; 63 | 64 | this.onClassSelected(TTClass.addClass(className)); 65 | } 66 | 67 | render(jsx, props) { 68 | let ui = 76 | 79 |
80 | 24 | 25 |
26 | 27 | this.refresh(); 28 | return ui; 29 | } 30 | 31 | private refresh() { 32 | this.ids.counter!.textContent = this.counter.toString(); 33 | } 34 | 35 | countUp() { 36 | this.counter++; 37 | this.refresh(); 38 | } 39 | 40 | countDown() { 41 | this.counter--; 42 | this.refresh(); 43 | } 44 | 45 | updateCode() { 46 | if (this.ids.editor != undefined) { 47 | let newSource = this.ids.editor.value; 48 | this.ttclass.setSource(newSource); 49 | TTClass.recompile(); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/Observable.tsx: -------------------------------------------------------------------------------- 1 | class Observable { 2 | private static firedObservers: Set> | null; 3 | private observers = new Set<(T) => void>(); 4 | 5 | addObserver(observer): void { 6 | this.observers.add(observer); 7 | } 8 | 9 | removeObserver(observer): void { 10 | this.observers.delete(observer); 11 | } 12 | 13 | didChange(): void { 14 | if (!Observable.firedObservers) 15 | setTimeout(Observable.fireAllObservers); 16 | Observable.firedObservers = new Set([this]); 17 | } 18 | 19 | private fireObservers(): void { 20 | let oldObservers = this.observers; 21 | this.observers = new Set<(T) => void>(); 22 | 23 | for (let observer of oldObservers) 24 | observer(this); 25 | 26 | } 27 | 28 | private static fireAllObservers(): void { 29 | let oldObservables = this.firedObservers; 30 | Observable.firedObservers = null; 31 | 32 | if (oldObservables) { 33 | for (let observable of oldObservables) 34 | observable.fireObservers(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/ProgressDialogue.tsx: -------------------------------------------------------------------------------- 1 | class ProgressDialogue extends UiComponent { 2 | protected ids = new class { 3 | progress?: HTMLDivElement; 4 | }; 5 | private title: string; 6 | private max: number; 7 | 8 | static async run(title, max) { 9 | let c = new ProgressDialogue(title, max); 10 | 11 | let jsx = c.newJsxFactory(); 12 | c.root = c.render(jsx, {}); 13 | document.body.appendChild(c.root!); 14 | await c.update(0); 15 | return c; 16 | } 17 | 18 | private constructor(title, max) { 19 | super({}); 20 | this.title = title; 21 | this.max = max; 22 | } 23 | 24 | async update(progress: number) { 25 | let percent = `${100 * progress / this.max}%`; 26 | this.ids.progress!.style.width = percent; 27 | } 28 | 29 | async close() { 30 | if (this.root) 31 | this.root.remove(); 32 | } 33 | 34 | render(jsx, props) { 35 | return 36 | 37 |
{this.title}
38 |
39 |
40 |
41 | 42 | 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/QueryDialogue.tsx: -------------------------------------------------------------------------------- 1 | class QueryDialogue extends UiComponent { 2 | protected ids = new class { 3 | text?: HTMLInputElement; 4 | }; 5 | private title: string; 6 | private question: string; 7 | private onresult: (result: string|null) => void; 8 | 9 | static run(title, question): Promise { 10 | return new Promise( 11 | (resolve, reject) => { 12 | let c = new QueryDialogue(title, question, 13 | (result) => { 14 | resolve(result); 15 | c.root!.remove(); 16 | } 17 | ); 18 | let jsx = c.newJsxFactory(); 19 | c.root = c.render(jsx, {}); 20 | document.body.appendChild(c.root!); 21 | } 22 | ); 23 | } 24 | 25 | constructor(title, question, onresult) { 26 | super({}); 27 | this.title = title; 28 | this.question = question; 29 | this.onresult = onresult 30 | } 31 | 32 | private onCancel() { 33 | this.onresult(null); 34 | } 35 | 36 | private onConfirm() { 37 | this.onresult(this.ids.text!.value); 38 | } 39 | 40 | render(jsx, props) { 41 | return this.onCancel()}> 43 | 44 |
{this.question}
45 | 46 | 47 | 48 | 49 | 50 |
51 |
52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/RunTestsRunnable.tsx: -------------------------------------------------------------------------------- 1 | class RunTestsRunnable extends Runnable { 2 | protected ids = new class { 3 | container?: HTMLElement; 4 | }; 5 | 6 | static title() { 7 | return "Run all tests"; 8 | } 9 | 10 | render(jsx, props) { 11 | return
12 |

Running tests

13 |
14 |
; 15 | } 16 | 17 | async run() { 18 | super.run(); 19 | 20 | let jsx = this.newJsxFactory(); 21 | for (let key of Object.getOwnPropertyNames(globals)) { 22 | let value = globals[key]; 23 | if (value && value.prototype && (value.prototype instanceof AbstractTest)) { 24 | try { 25 | new value().run(); 26 | this.ids.container!.appendChild( 27 |

{value.name}: passed

28 | ); 29 | } catch (e) { 30 | this.ids.container!.appendChild( 31 |

{value.name}: failed

32 |
{e}
33 | ); 34 | } 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Runnable.tsx: -------------------------------------------------------------------------------- 1 | abstract class Runnable extends UiComponent { 2 | async run() { 3 | if (!this.root) { 4 | this.root = this.render(this.newJsxFactory(), this.props); 5 | document.body.appendChild(this.root); 6 | } 7 | } 8 | 9 | onClose() { 10 | if (this.root) { 11 | this.root.remove(); 12 | this.root = undefined; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/jsx/DomAttributes.tsx: -------------------------------------------------------------------------------- 1 | interface DomAttributes { 2 | // Clipboard Events 3 | oncopy?: UiEventHandler; 4 | oncut?: UiEventHandler; 5 | onpaste?: UiEventHandler; 6 | 7 | // Composition Events 8 | oncompositionend?: UiEventHandler; 9 | oncompositionstart?: UiEventHandler; 10 | oncompositionupdate?: UiEventHandler; 11 | 12 | // Focus Events 13 | onfocus?: UiEventHandler; 14 | onblur?: UiEventHandler; 15 | 16 | // Form Events 17 | onchange?: UiEventHandler; 18 | oninput?: UiEventHandler; 19 | onsubmit?: UiEventHandler; 20 | 21 | // Keyboard Events 22 | onkeydown?: UiEventHandler; 23 | onkeypress?: UiEventHandler; 24 | onkeyup?: UiEventHandler; 25 | 26 | // Media Events 27 | onabort?: UiEventHandler; 28 | oncanplay?: UiEventHandler; 29 | oncanplaythrough?: UiEventHandler; 30 | ondurationchange?: UiEventHandler; 31 | onemptied?: UiEventHandler; 32 | onencrypted?: UiEventHandler; 33 | onended?: UiEventHandler; 34 | onloadeddata?: UiEventHandler; 35 | onloadedmetadata?: UiEventHandler; 36 | onloadstart?: UiEventHandler; 37 | onpause?: UiEventHandler; 38 | onplay?: UiEventHandler; 39 | onplaying?: UiEventHandler; 40 | onprogress?: UiEventHandler; 41 | onratechange?: UiEventHandler; 42 | onseeked?: UiEventHandler; 43 | onseeking?: UiEventHandler; 44 | onstalled?: UiEventHandler; 45 | onsuspend?: UiEventHandler; 46 | ontimeupdate?: UiEventHandler; 47 | onvolumechange?: UiEventHandler; 48 | onwaiting?: UiEventHandler; 49 | 50 | // MouseEvents 51 | onclick?: UiEventHandler; 52 | oncontextmenu?: UiEventHandler; 53 | ondoubleclick?: UiEventHandler; 54 | ondrag?: UiEventHandler; 55 | ondragend?: UiEventHandler; 56 | ondragenter?: UiEventHandler; 57 | ondragexit?: UiEventHandler; 58 | ondragleave?: UiEventHandler; 59 | ondragover?: UiEventHandler; 60 | ondragstart?: UiEventHandler; 61 | ondrop?: UiEventHandler; 62 | onmousedown?: UiEventHandler; 63 | onmouseenter?: UiEventHandler; 64 | onmouseleave?: UiEventHandler; 65 | onmousemove?: UiEventHandler; 66 | onmouseout?: UiEventHandler; 67 | onmouseover?: UiEventHandler; 68 | onmouseup?: UiEventHandler; 69 | 70 | // Selection Events 71 | onselect?: UiEventHandler; 72 | 73 | // Touch Events 74 | ontouchcancel?: UiEventHandler; 75 | ontouchend?: UiEventHandler; 76 | ontouchmove?: UiEventHandler; 77 | ontouchstart?: UiEventHandler; 78 | 79 | // UI Events 80 | onscroll?: UiEventHandler; 81 | 82 | // Wheel Events 83 | onwheel?: UiEventHandler; 84 | 85 | // Animation Events 86 | onanimationstart?: UiEventHandler; 87 | onanimationend?: UiEventHandler; 88 | onanimationiteration?: UiEventHandler; 89 | 90 | // Transition Events 91 | ontransitionend?: UiEventHandler; 92 | } 93 | -------------------------------------------------------------------------------- /src/jsx/HTMLComponentElement.tsx: -------------------------------------------------------------------------------- 1 | interface HTMLComponentElement extends HTMLElement { 2 | component?: Set>; 3 | ref?: (HTMLComponentElement) => void; 4 | } 5 | -------------------------------------------------------------------------------- /src/jsx/HtmlAttributes.tsx: -------------------------------------------------------------------------------- 1 | interface HtmlAttributes extends DomAttributes { 2 | // Standard HTML Attributes 3 | accept?: string; 4 | acceptCharset?: string; 5 | accessKey?: string; 6 | action?: string; 7 | allowFullScreen?: boolean; 8 | allowTransparency?: boolean; 9 | alt?: string; 10 | async?: boolean; 11 | autocomplete?: string; 12 | autofocus?: boolean; 13 | autoPlay?: boolean; 14 | capture?: boolean; 15 | cellPadding?: number | string; 16 | cellSpacing?: number | string; 17 | charSet?: string; 18 | challenge?: string; 19 | checked?: boolean; 20 | class?: string; 21 | cols?: number; 22 | colSpan?: number; 23 | content?: string; 24 | contentEditable?: boolean; 25 | contextMenu?: string; 26 | controls?: boolean; 27 | coords?: string; 28 | crossOrigin?: string; 29 | data?: string; 30 | dateTime?: string; 31 | default?: boolean; 32 | defer?: boolean; 33 | dir?: string; 34 | disabled?: boolean; 35 | download?: any; 36 | draggable?: boolean; 37 | encType?: string; 38 | form?: string; 39 | formAction?: string; 40 | formEncType?: string; 41 | formMethod?: string; 42 | formNoValidate?: boolean; 43 | formTarget?: string; 44 | frameBorder?: number | string; 45 | headers?: string; 46 | height?: number | string; 47 | hidden?: boolean; 48 | high?: number; 49 | href?: string; 50 | hrefLang?: string; 51 | for?: string; 52 | httpEquiv?: string; 53 | icon?: string; 54 | id?: string; 55 | inputMode?: string; 56 | integrity?: string; 57 | is?: string; 58 | keyParams?: string; 59 | keyType?: string; 60 | kind?: string; 61 | label?: string; 62 | lang?: string; 63 | list?: string; 64 | loop?: boolean; 65 | low?: number; 66 | manifest?: string; 67 | marginHeight?: number; 68 | marginWidth?: number; 69 | max?: number | string; 70 | maxLength?: number; 71 | media?: string; 72 | mediaGroup?: string; 73 | method?: string; 74 | min?: number | string; 75 | minLength?: number; 76 | multiple?: boolean; 77 | muted?: boolean; 78 | name?: string; 79 | noValidate?: boolean; 80 | open?: boolean; 81 | optimum?: number; 82 | pattern?: string; 83 | placeholder?: string; 84 | poster?: string; 85 | preload?: string; 86 | radioGroup?: string; 87 | readOnly?: boolean; 88 | rel?: string; 89 | required?: boolean; 90 | role?: string; 91 | rows?: number; 92 | rowSpan?: number; 93 | sandbox?: string; 94 | scope?: string; 95 | scoped?: boolean; 96 | scrolling?: string; 97 | seamless?: boolean; 98 | selected?: boolean; 99 | shape?: string; 100 | size?: number; 101 | sizes?: string; 102 | span?: number; 103 | spellCheck?: boolean; 104 | src?: string; 105 | srcset?: string; 106 | srcDoc?: string; 107 | srcLang?: string; 108 | srcSet?: string; 109 | start?: number; 110 | step?: number | string; 111 | style?: any; 112 | summary?: string; 113 | tabIndex?: number; 114 | target?: string; 115 | title?: string; 116 | type?: string; 117 | useMap?: string; 118 | value?: string | string[]; 119 | width?: number | string; 120 | wmode?: string; 121 | wrap?: string; 122 | 123 | // RDFa Attributes 124 | about?: string; 125 | datatype?: string; 126 | inlist?: any; 127 | prefix?: string; 128 | property?: string; 129 | resource?: string; 130 | typeof?: string; 131 | vocab?: string; 132 | } 133 | -------------------------------------------------------------------------------- /src/jsx/JsxDraggable.tsx: -------------------------------------------------------------------------------- 1 | class JsxDraggable extends UiComponent { 2 | private onMouseDown(me: MouseEvent) { 3 | me.preventDefault(); 4 | if (this.props.onBegin) 5 | this.props.onBegin(me.clientX, me.clientY); 6 | document.onmousemove = me => this.onMouseMove(me); 7 | document.onmouseup = me => this.onMouseUp(me); 8 | return false; 9 | } 10 | 11 | private onMouseMove(me: MouseEvent) { 12 | me.preventDefault(); 13 | if (this.props.onMove) 14 | this.props.onMove(me.clientX, me.clientY); 15 | return false; 16 | } 17 | 18 | private onMouseUp(me: MouseEvent) { 19 | this.onMouseMove(me); 20 | if (this.props.onEnd) 21 | this.props.onEnd(me.clientX, me.clientY); 22 | document.onmousemove = null; 23 | document.onmouseup = null; 24 | return false; 25 | } 26 | 27 | render(jsx, props) { 28 | return
this.onMouseDown(me)}> 32 | { props.children } 33 |
; 34 | } 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /src/jsx/JsxDraggableProps.tsx: -------------------------------------------------------------------------------- 1 | class JsxDraggableProps { 2 | style?: any; 3 | class?: string; 4 | onBegin?: (x: number, y: number) => void; 5 | onMove?: (x: number, y: number) => void; 6 | onEnd?: (x: number, y: number) => void; 7 | } -------------------------------------------------------------------------------- /src/jsx/JsxGrid.tsx: -------------------------------------------------------------------------------- 1 | class JsxGrid extends UiComponent { 2 | render(jsx, props) { 3 | let style = { 4 | "display": "grid", 5 | "grid-template-columns": props.columns, 6 | "grid-template-rows": props.rows, 7 | ...props.style 8 | }; 9 | if (props.template) 10 | style["grid-template-areas"] = props.template.map(s => `"${s}"`).join(" "); 11 | 12 | return
13 | {props.children} 14 |
; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/jsx/JsxGridProps.tsx: -------------------------------------------------------------------------------- 1 | class JsxGridProps { 2 | id?: string; 3 | style?: any; 4 | class?: string; 5 | columns?: string; 6 | rows?: string; 7 | template?: string[]; 8 | } 9 | -------------------------------------------------------------------------------- /src/jsx/JsxHBox.tsx: -------------------------------------------------------------------------------- 1 | class JsxHBox extends UiComponent { 2 | render(jsx, props) { 3 | let style = { 4 | "display": "grid", 5 | "grid-auto-flow": "column", 6 | "grid-auto-columns": "1fr", 7 | ...props.style 8 | }; 9 | 10 | return
11 | {props.children} 12 |
; 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/jsx/JsxVBox.tsx: -------------------------------------------------------------------------------- 1 | class JsxVBox extends UiComponent { 2 | render(jsx, props) { 3 | let style = { 4 | "display": "grid", 5 | "grid-auto-flow": "row", 6 | "grid-auto-columns": "1fr", 7 | ...props.style 8 | }; 9 | 10 | return
11 | {props.children} 12 |
; 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/jsx/JsxWindow.tsx: -------------------------------------------------------------------------------- 1 | class JsxWindow extends UiComponent { 2 | private startX = 0; 3 | private startY = 0; 4 | 5 | private onMoveBegin(x: number, y: number) { 6 | let [winX, winY] = this.getPosition(); 7 | this.startX = winX - x; 8 | this.startY = winY - y; 9 | } 10 | 11 | private onMoveDrag(x: number, y: number) { 12 | if (this.root) { 13 | this.root.style.left = `${this.startX + x}px`; 14 | this.root.style.top = `${this.startY + y}px`; 15 | } 16 | } 17 | 18 | private onResizeBegin(x: number, y: number) { 19 | let [winX, winY] = this.getSize(); 20 | this.startX = winX - x; 21 | this.startY = winY - y; 22 | } 23 | 24 | private onResizeDrag(x: number, y: number) { 25 | let props = this.props; 26 | let minW = props.minWidth || 128; 27 | let minH = props.minHeight || 128; 28 | 29 | let newW = this.startX + x; 30 | if (newW < minW) 31 | newW = minW 32 | let newH = this.startY + y; 33 | if (newH < minH) 34 | newH = minH; 35 | 36 | if (this.root) { 37 | this.root.style.width = `${newW}px`; 38 | this.root.style.height = `${newH}px`; 39 | } 40 | } 41 | 42 | onClose() { 43 | if (this.props.onClose) 44 | this.props.onClose(); 45 | } 46 | 47 | getMinimumSize(): [number, number] { 48 | return [128, 128]; 49 | } 50 | 51 | render(jsx, props) { 52 | let style = { 53 | left: props.x, 54 | top: props.y, 55 | width: props.width, 56 | height: props.height, 57 | ...props.style 58 | }; 59 | 60 | return 63 | this.onMoveBegin(x, y)} 65 | onMove={(x, y) => this.onMoveDrag(x, y)} 66 | > 67 |
68 |
{props.title}
69 | {props.onClose &&
72 |
73 |
74 | {props.children} 75 |
76 | {props.resizeable && 77 | this.onResizeBegin(x, y)} 80 | onMove={(x, y) => this.onResizeDrag(x, y)} 81 | /> 82 | } 83 |
; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/jsx/JsxWindowProps.tsx: -------------------------------------------------------------------------------- 1 | class JsxWindowProps { 2 | title: string = ""; 3 | id?: string; 4 | class?: string; 5 | style?: any; 6 | resizeable?: boolean; 7 | x?: string; 8 | y?: string; 9 | width?: string; 10 | height?: string; 11 | minWidth?: number; 12 | minHeight?: number; 13 | 14 | onClose?: () => void; 15 | }; 16 | -------------------------------------------------------------------------------- /src/jsx/UiComponent.tsx: -------------------------------------------------------------------------------- 1 | abstract class UiComponent { 2 | root?: HTMLComponentElement; 3 | protected ids: any = {}; 4 | protected props: PropsT; 5 | 6 | constructor(props: PropsT) { 7 | this.props = props; 8 | } 9 | 10 | newJsxFactory() { 11 | let rootComponent = this; 12 | 13 | function jsxFactory(node: UiComponentConstructor, params: PropsST, 14 | ...children: (Element | string | undefined)[]); 15 | function jsxFactory(tag: string, params: HtmlAttributes, 16 | ...children: (Element | string | undefined)[]); 17 | function jsxFactory(kind: UiComponentConstructor | string, 18 | params, ...children) { 19 | if (params == null) 20 | params = {}; 21 | 22 | let e: HTMLComponentElement; 23 | if (typeof kind === "string") { 24 | e = document.createElement(kind) as HTMLElement; 25 | for (let key in params) { 26 | let value = params[key]; 27 | if (key === "class") 28 | key = "className"; 29 | 30 | if (typeof value === "object") { 31 | if (key === "style") { 32 | for (let k in value) { 33 | let v = value[k]; 34 | if (v != undefined) 35 | e.style[k] = v; 36 | } 37 | } else 38 | throw `can't use an object for a '${key}' parameter`; 39 | } else if (value != undefined) 40 | e[key] = value; 41 | } 42 | 43 | function recursivelyAddChildren(children: (Element | undefined | Element[])[]) { 44 | for (let child of children) { 45 | if (child === undefined) 46 | continue; 47 | else if (child.constructor === Array) 48 | recursivelyAddChildren(child as Element[]); 49 | else if (child instanceof Element) 50 | e.appendChild(child); 51 | else 52 | e.appendChild(document.createTextNode(child.toString())); 53 | } 54 | } 55 | 56 | recursivelyAddChildren(children); 57 | 58 | if (params.id) 59 | rootComponent.ids[params.id] = e; 60 | } else { 61 | params.children = children; 62 | let componentConstructor = kind as UiComponentConstructor; 63 | let subc = new componentConstructor(params); 64 | 65 | e = subc.render(subc.newJsxFactory(), params); 66 | subc.root = e; 67 | 68 | if (params.id) 69 | rootComponent.ids[params.id] = subc; 70 | } 71 | 72 | return e; 73 | } 74 | 75 | return jsxFactory; 76 | } 77 | 78 | abstract render(jsx: { 79 | (node: UiComponentConstructor, params: PropsST, 80 | ...children: (Element | string | undefined)[]): HTMLComponentElement 81 | (tag: string, params: HtmlAttributes, 82 | ...children: (Element | string | undefined)[]): HTMLComponentElement 83 | }, props: PropsT): HTMLComponentElement; 84 | 85 | /* Miscellaneous utility methods */ 86 | 87 | private static fromPixels(s: string | null): number { 88 | if (s) 89 | return +s.replace(/px$/, ""); 90 | return 0; 91 | } 92 | 93 | getPosition(): [number, number] { 94 | if (!this.root) 95 | return [0, 0]; 96 | let computed = window.getComputedStyle(this.root.parentElement!); 97 | let winX = this.root.offsetLeft - UiComponent.fromPixels(computed.borderLeftWidth); 98 | let winY = this.root.offsetTop - UiComponent.fromPixels(computed.borderTopWidth); 99 | return [winX, winY]; 100 | } 101 | 102 | getSize(): [number, number] { 103 | if (!this.root) 104 | return [0, 0]; 105 | return [this.root.clientWidth, this.root.clientHeight]; 106 | } 107 | 108 | isAttached(): boolean { 109 | function is_attached(node) { 110 | if (!node) 111 | return false; 112 | if (node.nodeType === Node.DOCUMENT_NODE) 113 | return true; 114 | if (node.parentNode == undefined) 115 | return false; 116 | return is_attached(node.parentNode); 117 | } 118 | 119 | return is_attached(this.root); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/jsx/UiComponentConstructor.tsx: -------------------------------------------------------------------------------- 1 | interface UiComponentConstructor { 2 | new (props?: PropsT): UiComponent; 3 | } 4 | -------------------------------------------------------------------------------- /src/jsx/UiEventHandler.tsx: -------------------------------------------------------------------------------- 1 | interface UiEventHandler { 2 | (event: E): void; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /src/tests/AbstractTest.tsx: -------------------------------------------------------------------------------- 1 | abstract class AbstractTest { 2 | abstract run(): void; 3 | 4 | assert(condition: boolean, message: string): void { 5 | if (!condition) 6 | throw message; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/tests/RemoveMethodBelongingToSuperclassTest.tsx: -------------------------------------------------------------------------------- 1 | class RemoveMethodBelongingToSuperclassTest extends AbstractTest { 2 | run() { 3 | let testClass = TTClass.addClass("TestClass"); 4 | let testSubclass = TTClass.addClass("TestSubclass"); 5 | 6 | testClass.setSource(` 7 | class TestClass { 8 | m(): number { return 1; } 9 | }; 10 | `); 11 | 12 | testSubclass.setSource(` 13 | class TestSubclass extends TestClass { 14 | m(): number { return 2; } 15 | }; 16 | `); 17 | 18 | TTClass.recompile(); 19 | let o = new globals.TestSubclass(); 20 | this.assert(o.m() == 2, "incorrect value calculated"); 21 | 22 | testSubclass.setSource(` 23 | class TestSubclass extends TestClass { 24 | }; 25 | `); 26 | TTClass.recompile(); 27 | 28 | this.assert(o.m() == 1, "incorrect value after method removed"); 29 | o = new globals.TestSubclass(); 30 | this.assert(o.m() == 1, "incorrect value after method removed and new object"); 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/tests/SuperKeywordInConstructorTest.tsx: -------------------------------------------------------------------------------- 1 | class SuperKeywordInConstructorTest extends AbstractTest { 2 | run() { 3 | TTClass.addClass("TestClass").setSource(` 4 | class TestClass { 5 | value: number; 6 | 7 | constructor(v) { 8 | this.value = v; 9 | } 10 | }; 11 | `); 12 | 13 | TTClass.addClass("TestSubclass").setSource(` 14 | class TestSubclass extends TestClass { 15 | constructor() { 16 | super(7); 17 | } 18 | }; 19 | `); 20 | 21 | TTClass.recompile(); 22 | let o = new globals.TestSubclass(); 23 | this.assert(o.value == 7, "incorrect value calculated"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/tests/SuperKeywordInMethodTest.tsx: -------------------------------------------------------------------------------- 1 | class SuperKeywordInMethodTest extends AbstractTest { 2 | run() { 3 | TTClass.addClass("TestClass").setSource(` 4 | class TestClass { 5 | m(): number { return 1; } 6 | }; 7 | `); 8 | 9 | TTClass.addClass("TestSubclass").setSource(` 10 | class TestSubclass extends TestClass { 11 | m(): number { return super.m() + 1; } 12 | }; 13 | `); 14 | 15 | TTClass.recompile(); 16 | let o = new globals.TestSubclass(); 17 | this.assert(o.m() == 2, "incorrect value calculated"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/tests/UpdateClassConstructorTest.tsx: -------------------------------------------------------------------------------- 1 | class UpdateClassConstructorTest extends AbstractTest { 2 | run() { 3 | TTClass.addClass("TestClass").setSource(` 4 | class TestClass { 5 | static result: number; 6 | constructor() { 7 | TestClass.result = 1; 8 | } 9 | }; 10 | `); 11 | TTClass.addClass("TestSubclass").setSource(` 12 | class TestSubclass {} 13 | `); 14 | 15 | TTClass.recompile(); 16 | let o = new globals.TestClass(); 17 | this.assert(globals.TestClass.result == 1, "superclass constructor did not fire"); 18 | } 19 | } -------------------------------------------------------------------------------- /src/tests/UpdateClassMethodTest.tsx: -------------------------------------------------------------------------------- 1 | class UpdateClassMethodTest extends AbstractTest { 2 | run() { 3 | TTClass.addClass("TestClass").setSource( ` 4 | class TestClass { 5 | m(): number { return 1; } 6 | }; 7 | `); 8 | TTClass.addClass("TestSubclass").setSource(` 9 | class TestSubclass {} 10 | `); 11 | 12 | TTClass.recompile(); 13 | let o = new globals.TestClass(); 14 | this.assert(o.m() == 1, "method did not fire"); 15 | 16 | TTClass.addClass("TestClass").setSource(` 17 | class TestClass { 18 | m(): number { return 2; } 19 | }; 20 | `); 21 | TTClass.recompile(); 22 | 23 | this.assert(o.m() == 2, "updated method did not fire"); 24 | } 25 | } -------------------------------------------------------------------------------- /src/tests/UpdateSuperclassConstructorTest.tsx: -------------------------------------------------------------------------------- 1 | class UpdateSuperclassConstructorTest extends AbstractTest { 2 | run() { 3 | TTClass.addClass("TestClass").setSource(` 4 | class TestClass { 5 | static result: number; 6 | constructor() { 7 | TestClass.result = 1; 8 | } 9 | }; 10 | `); 11 | 12 | TTClass.addClass("TestSubclass").setSource(` 13 | class TestSubclass extends TestClass { 14 | }; 15 | `); 16 | 17 | TTClass.recompile(); 18 | let o = new globals.TestSubclass(); 19 | this.assert(globals.TestClass.result == 1, "superclass constructor did not fire"); 20 | 21 | TTClass.addClass("TestClass").setSource(` 22 | class TestClass { 23 | static result: number; 24 | constructor() { 25 | TestClass.result = 2; 26 | } 27 | }; 28 | `); 29 | TTClass.recompile(); 30 | 31 | o = new globals.TestSubclass(); 32 | this.assert(globals.TestClass.result == 2, "updated superclass constructor did not fire"); 33 | } 34 | } -------------------------------------------------------------------------------- /src/tests/UpdateSuperclassMethodTest.tsx: -------------------------------------------------------------------------------- 1 | class UpdateSuperclassMethodTest extends AbstractTest { 2 | run() { 3 | TTClass.addClass("TestClass").setSource(` 4 | class TestClass { 5 | m(): number { return 1; } 6 | }; 7 | `); 8 | 9 | TTClass.addClass("TestSubclass").setSource(` 10 | class TestSubclass extends TestClass { 11 | }; 12 | `); 13 | 14 | TTClass.recompile(); 15 | let o = new globals.TestSubclass(); 16 | this.assert(o.m() == 1, "superclass method did not fire"); 17 | 18 | TTClass.addClass("TestClass").setSource(` 19 | class TestClass { 20 | m(): number { return 2; } 21 | }; 22 | `); 23 | TTClass.recompile(); 24 | 25 | this.assert(o.m() == 2, "updated superclass method did not fire"); 26 | } 27 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "jsxFactory": "jsx", 5 | "noImplicitAny": false, 6 | "strict": true, 7 | "target": "es2017", 8 | } 9 | } --------------------------------------------------------------------------------