├── .github └── workflows │ └── ci.yml ├── README.md ├── bootstrap.ts ├── domino ├── domino.mjs └── event.mjs ├── engine.ts ├── example ├── README.md ├── app.component.css ├── app.component.html ├── app.component.ts ├── app.module.ts ├── importmap.json ├── index.html ├── main.test.ts ├── main.ts ├── server.ts └── tsconfig.json ├── mod.ts ├── platform-server.mjs └── resource-loader.ts /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-18.04 8 | strategy: 9 | matrix: 10 | deno: [1.15.1] 11 | name: Deno ${{ matrix.deno }} 12 | steps: 13 | - uses: actions/checkout@master 14 | - name: Setup deno 15 | uses: denolib/setup-deno@master 16 | with: 17 | deno-version: ${{ matrix.deno }} 18 | - name: Test example 19 | working-directory: ./example 20 | run: deno test --importmap=importmap.json --location=https://jspm.dev --allow-read 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular renderer in Deno 2 | 3 | ![test](https://github.com/alosaur/angular_deno/workflows/test/badge.svg) 4 | 5 | Now Supported Angular 12.0.3 and Deno 1.14.0 6 | 7 | This is experimental Angular SSR in Deno, and will be used as a renderer for [Alosaur](https://github.com/alosaur/alosaur) web framework, as well as handlebars, ejs, mustache. 8 | 9 | ## How to use 10 | 11 | `deno run --importmap=importmap.json --location=https://jspm.dev --allow-read main.ts` 12 | 13 | Declare Angular deps 14 | 15 | importmap.json: 16 | ```json 17 | { 18 | "imports": { 19 | "@angular/core": "https://jspm.dev/@angular/core@12.0.3", 20 | "@angular/deno": "https://deno.land/x/angular_deno/mod.ts", 21 | "@angular/deno/": "https://deno.land/x/angular_deno/", 22 | "reflect": "https://deno.land/x/alosaur@v0.34.0/src/injection/reflect.ts", 23 | "zone.js": "https://jspm.dev/zone.js/dist/zone" 24 | } 25 | } 26 | ``` 27 | 28 | main.ts: 29 | 30 | ```ts 31 | import { CompilerFactory, enableProdMode } from '@angular/core'; 32 | import { bootstrap, CommonEngine } from '@angular/deno'; 33 | import { AppModule } from './app.module.ts'; 34 | 35 | import "reflect"; 36 | import 'zone.js'; 37 | 38 | const { readFile } = Deno; 39 | const decoder = new TextDecoder(); 40 | 41 | // Read index.html for root parse 42 | const indexHtml = decoder.decode(await readFile('index.html')); 43 | 44 | enableProdMode(); 45 | 46 | // bootstrap main app 47 | const ref: any = await bootstrap(AppModule, indexHtml); 48 | 49 | // create renderer engine 50 | const engine = new CommonEngine(ref.injector.get(CompilerFactory), AppModule); 51 | 52 | 53 | // Render page for URL 54 | const page: string = await engine.render({ document: indexHtml, url: "/" }); 55 | ``` 56 | 57 | app.module.ts: 58 | 59 | ```ts 60 | import { NgModule } from '@angular/core'; 61 | import { ServerModule } from '@angular/deno'; 62 | import { AppComponent } from './app.component.ts'; 63 | 64 | 65 | @NgModule({ 66 | imports: [ServerModule], 67 | declarations: [AppComponent], 68 | bootstrap: [AppComponent], 69 | providers: [] 70 | }) 71 | export class AppModule { } 72 | ``` 73 | 74 | ## TODO 75 | 76 | If the "stars" on this project will be more than 100 ;) 77 | 78 | - [ ] Transfer state 79 | - [ ] AOT 80 | - [ ] SASS support 81 | 82 | ### Note 83 | 84 | All .mjs files in this repository exported from jspm.dev as ESM module, for example: 85 | https://jspm.dev/npm:@angular/platform-server@10.2.4!cjs 86 | 87 | Why platform-server.mjs exported from jspm and not rewrite DominoAdapter? 88 | I do not remember, maybe something broke at the moment of redefining providers 89 | https://github.com/angular/angular/blob/a6971ba89adc253bfa4260036ee4a1e0bd76159f/packages/platform-server/src/server.ts#L33 90 | -------------------------------------------------------------------------------- /bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { createPlatformFactory, Injector, COMPILER_OPTIONS, InjectionToken } from 'https://jspm.dev/@angular/core@12.0.3'; 2 | import { ɵplatformCoreDynamic } from 'https://jspm.dev/@angular/platform-browser-dynamic@12.0.3'; 3 | import { ResourceLoader } from 'https://jspm.dev/@angular/compiler@12.0.3'; 4 | import { INITIAL_CONFIG, ɵINTERNAL_SERVER_PLATFORM_PROVIDERS as INTERNAL_SERVER_PLATFORM_PROVIDERS } from './platform-server.mjs'; 5 | import { DenoFileSystemResourceLoader } from './resource-loader.ts'; 6 | 7 | export const RESOURCE_PATH = new InjectionToken('RESOURCE_PATH'); 8 | 9 | const platformDenoDynamicServer = (resourcePath: string) => createPlatformFactory(ɵplatformCoreDynamic, "serverDenoDynamic", 10 | [...INTERNAL_SERVER_PLATFORM_PROVIDERS, 11 | { 12 | provide: COMPILER_OPTIONS, 13 | useValue: { 14 | providers: [ 15 | { 16 | provide: RESOURCE_PATH, 17 | useValue: resourcePath 18 | }, 19 | { 20 | provide: ResourceLoader, 21 | useClass: DenoFileSystemResourceLoader, 22 | deps: [Injector] 23 | } 24 | ] 25 | }, 26 | multi: true 27 | } 28 | ]); 29 | 30 | export async function bootstrap(module: any, document: string, resourcePath: string = "") { 31 | return Promise.resolve(platformDenoDynamicServer(resourcePath)([ 32 | { 33 | provide: INITIAL_CONFIG, 34 | useValue: { 35 | document, 36 | url: '/' 37 | } 38 | }]).bootstrapModule(module, { ngZone: 'noop' }).then((ref: any) => { 39 | return Promise.resolve(ref) 40 | })); 41 | } 42 | -------------------------------------------------------------------------------- /domino/event.mjs: -------------------------------------------------------------------------------- 1 | var exports = {}, 2 | _dewExec = false; 3 | function dew() { 4 | if (_dewExec) return exports; 5 | _dewExec = true; 6 | exports = Event; 7 | Event.CAPTURING_PHASE = 1; 8 | Event.AT_TARGET = 2; 9 | Event.BUBBLING_PHASE = 3; 10 | 11 | function Event(type, dictionary) { 12 | // Initialize basic event properties 13 | this.type = ""; 14 | this.target = null; 15 | this.currentTarget = null; 16 | this.eventPhase = Event.AT_TARGET; 17 | this.bubbles = false; 18 | this.cancelable = false; 19 | this.isTrusted = false; 20 | this.defaultPrevented = false; 21 | this.timeStamp = Date.now(); // Initialize internal flags 22 | // XXX: Would it be better to inherit these defaults from the prototype? 23 | 24 | this._propagationStopped = false; 25 | this._immediatePropagationStopped = false; 26 | this._initialized = true; 27 | this._dispatching = false; // Now initialize based on the constructor arguments (if any) 28 | 29 | if (type) this.type = type; 30 | 31 | if (dictionary) { 32 | for (var p in dictionary) { 33 | this[p] = dictionary[p]; 34 | } 35 | } 36 | } 37 | 38 | Event.prototype = Object.create(Object.prototype, { 39 | constructor: { 40 | value: Event 41 | }, 42 | stopPropagation: { 43 | value: function stopPropagation() { 44 | this._propagationStopped = true; 45 | } 46 | }, 47 | stopImmediatePropagation: { 48 | value: function stopImmediatePropagation() { 49 | this._propagationStopped = true; 50 | this._immediatePropagationStopped = true; 51 | } 52 | }, 53 | preventDefault: { 54 | value: function preventDefault() { 55 | if (this.cancelable) this.defaultPrevented = true; 56 | } 57 | }, 58 | initEvent: { 59 | value: function initEvent(type, bubbles, cancelable) { 60 | this._initialized = true; 61 | if (this._dispatching) return; 62 | this._propagationStopped = false; 63 | this._immediatePropagationStopped = false; 64 | this.defaultPrevented = false; 65 | this.isTrusted = false; 66 | this.target = null; 67 | this.type = type; 68 | this.bubbles = bubbles; 69 | this.cancelable = cancelable; 70 | } 71 | } 72 | }); 73 | return exports; 74 | } 75 | 76 | var exports$1 = {}, 77 | _dewExec$1 = false; 78 | function dew$1() { 79 | if (_dewExec$1) return exports$1; 80 | _dewExec$1 = true; 81 | 82 | var Event = dew(); 83 | 84 | exports$1 = UIEvent; 85 | 86 | function UIEvent() { 87 | // Just use the superclass constructor to initialize 88 | Event.call(this); 89 | this.view = null; // FF uses the current window 90 | 91 | this.detail = 0; 92 | } 93 | 94 | UIEvent.prototype = Object.create(Event.prototype, { 95 | constructor: { 96 | value: UIEvent 97 | }, 98 | initUIEvent: { 99 | value: function (type, bubbles, cancelable, view, detail) { 100 | this.initEvent(type, bubbles, cancelable); 101 | this.view = view; 102 | this.detail = detail; 103 | } 104 | } 105 | }); 106 | return exports$1; 107 | } 108 | 109 | var exports$2 = {}, 110 | _dewExec$2 = false; 111 | function dew$2() { 112 | if (_dewExec$2) return exports$2; 113 | _dewExec$2 = true; 114 | 115 | var UIEvent = dew$1(); 116 | 117 | exports$2 = MouseEvent; 118 | 119 | function MouseEvent() { 120 | // Just use the superclass constructor to initialize 121 | UIEvent.call(this); 122 | this.screenX = this.screenY = this.clientX = this.clientY = 0; 123 | this.ctrlKey = this.altKey = this.shiftKey = this.metaKey = false; 124 | this.button = 0; 125 | this.buttons = 1; 126 | this.relatedTarget = null; 127 | } 128 | 129 | MouseEvent.prototype = Object.create(UIEvent.prototype, { 130 | constructor: { 131 | value: MouseEvent 132 | }, 133 | initMouseEvent: { 134 | value: function (type, bubbles, cancelable, view, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget) { 135 | this.initEvent(type, bubbles, cancelable, view, detail); 136 | this.screenX = screenX; 137 | this.screenY = screenY; 138 | this.clientX = clientX; 139 | this.clientY = clientY; 140 | this.ctrlKey = ctrlKey; 141 | this.altKey = altKey; 142 | this.shiftKey = shiftKey; 143 | this.metaKey = metaKey; 144 | this.button = button; 145 | 146 | switch (button) { 147 | case 0: 148 | this.buttons = 1; 149 | break; 150 | 151 | case 1: 152 | this.buttons = 4; 153 | break; 154 | 155 | case 2: 156 | this.buttons = 2; 157 | break; 158 | 159 | default: 160 | this.buttons = 0; 161 | break; 162 | } 163 | 164 | this.relatedTarget = relatedTarget; 165 | } 166 | }, 167 | getModifierState: { 168 | value: function (key) { 169 | switch (key) { 170 | case "Alt": 171 | return this.altKey; 172 | 173 | case "Control": 174 | return this.ctrlKey; 175 | 176 | case "Shift": 177 | return this.shiftKey; 178 | 179 | case "Meta": 180 | return this.metaKey; 181 | 182 | default: 183 | return false; 184 | } 185 | } 186 | } 187 | }); 188 | return exports$2; 189 | } 190 | 191 | var exports$3 = {}, 192 | _dewExec$3 = false; 193 | function dew$3() { 194 | if (_dewExec$3) return exports$3; 195 | _dewExec$3 = true; 196 | exports$3 = DOMException; 197 | var INDEX_SIZE_ERR = 1; 198 | var HIERARCHY_REQUEST_ERR = 3; 199 | var WRONG_DOCUMENT_ERR = 4; 200 | var INVALID_CHARACTER_ERR = 5; 201 | var NO_MODIFICATION_ALLOWED_ERR = 7; 202 | var NOT_FOUND_ERR = 8; 203 | var NOT_SUPPORTED_ERR = 9; 204 | var INVALID_STATE_ERR = 11; 205 | var SYNTAX_ERR = 12; 206 | var INVALID_MODIFICATION_ERR = 13; 207 | var NAMESPACE_ERR = 14; 208 | var INVALID_ACCESS_ERR = 15; 209 | var TYPE_MISMATCH_ERR = 17; 210 | var SECURITY_ERR = 18; 211 | var NETWORK_ERR = 19; 212 | var ABORT_ERR = 20; 213 | var URL_MISMATCH_ERR = 21; 214 | var QUOTA_EXCEEDED_ERR = 22; 215 | var TIMEOUT_ERR = 23; 216 | var INVALID_NODE_TYPE_ERR = 24; 217 | var DATA_CLONE_ERR = 25; // Code to name 218 | 219 | var names = [null, // No error with code 0 220 | "INDEX_SIZE_ERR", null, // historical 221 | "HIERARCHY_REQUEST_ERR", "WRONG_DOCUMENT_ERR", "INVALID_CHARACTER_ERR", null, // historical 222 | "NO_MODIFICATION_ALLOWED_ERR", "NOT_FOUND_ERR", "NOT_SUPPORTED_ERR", "INUSE_ATTRIBUTE_ERR", // historical 223 | "INVALID_STATE_ERR", "SYNTAX_ERR", "INVALID_MODIFICATION_ERR", "NAMESPACE_ERR", "INVALID_ACCESS_ERR", null, // historical 224 | "TYPE_MISMATCH_ERR", "SECURITY_ERR", "NETWORK_ERR", "ABORT_ERR", "URL_MISMATCH_ERR", "QUOTA_EXCEEDED_ERR", "TIMEOUT_ERR", "INVALID_NODE_TYPE_ERR", "DATA_CLONE_ERR"]; // Code to message 225 | // These strings are from the 13 May 2011 Editor's Draft of DOM Core. 226 | // http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html 227 | // Copyright В© 2011 W3CВ® (MIT, ERCIM, Keio), All Rights Reserved. 228 | // Used under the terms of the W3C Document License: 229 | // http://www.w3.org/Consortium/Legal/2002/copyright-documents-20021231 230 | 231 | var messages = [null, // No error with code 0 232 | "INDEX_SIZE_ERR (1): the index is not in the allowed range", null, "HIERARCHY_REQUEST_ERR (3): the operation would yield an incorrect nodes model", "WRONG_DOCUMENT_ERR (4): the object is in the wrong Document, a call to importNode is required", "INVALID_CHARACTER_ERR (5): the string contains invalid characters", null, "NO_MODIFICATION_ALLOWED_ERR (7): the object can not be modified", "NOT_FOUND_ERR (8): the object can not be found here", "NOT_SUPPORTED_ERR (9): this operation is not supported", "INUSE_ATTRIBUTE_ERR (10): setAttributeNode called on owned Attribute", "INVALID_STATE_ERR (11): the object is in an invalid state", "SYNTAX_ERR (12): the string did not match the expected pattern", "INVALID_MODIFICATION_ERR (13): the object can not be modified in this way", "NAMESPACE_ERR (14): the operation is not allowed by Namespaces in XML", "INVALID_ACCESS_ERR (15): the object does not support the operation or argument", null, "TYPE_MISMATCH_ERR (17): the type of the object does not match the expected type", "SECURITY_ERR (18): the operation is insecure", "NETWORK_ERR (19): a network error occurred", "ABORT_ERR (20): the user aborted an operation", "URL_MISMATCH_ERR (21): the given URL does not match another URL", "QUOTA_EXCEEDED_ERR (22): the quota has been exceeded", "TIMEOUT_ERR (23): a timeout occurred", "INVALID_NODE_TYPE_ERR (24): the supplied node is invalid or has an invalid ancestor for this operation", "DATA_CLONE_ERR (25): the object can not be cloned."]; // Name to code 233 | 234 | var constants = { 235 | INDEX_SIZE_ERR: INDEX_SIZE_ERR, 236 | DOMSTRING_SIZE_ERR: 2, 237 | // historical 238 | HIERARCHY_REQUEST_ERR: HIERARCHY_REQUEST_ERR, 239 | WRONG_DOCUMENT_ERR: WRONG_DOCUMENT_ERR, 240 | INVALID_CHARACTER_ERR: INVALID_CHARACTER_ERR, 241 | NO_DATA_ALLOWED_ERR: 6, 242 | // historical 243 | NO_MODIFICATION_ALLOWED_ERR: NO_MODIFICATION_ALLOWED_ERR, 244 | NOT_FOUND_ERR: NOT_FOUND_ERR, 245 | NOT_SUPPORTED_ERR: NOT_SUPPORTED_ERR, 246 | INUSE_ATTRIBUTE_ERR: 10, 247 | // historical 248 | INVALID_STATE_ERR: INVALID_STATE_ERR, 249 | SYNTAX_ERR: SYNTAX_ERR, 250 | INVALID_MODIFICATION_ERR: INVALID_MODIFICATION_ERR, 251 | NAMESPACE_ERR: NAMESPACE_ERR, 252 | INVALID_ACCESS_ERR: INVALID_ACCESS_ERR, 253 | VALIDATION_ERR: 16, 254 | // historical 255 | TYPE_MISMATCH_ERR: TYPE_MISMATCH_ERR, 256 | SECURITY_ERR: SECURITY_ERR, 257 | NETWORK_ERR: NETWORK_ERR, 258 | ABORT_ERR: ABORT_ERR, 259 | URL_MISMATCH_ERR: URL_MISMATCH_ERR, 260 | QUOTA_EXCEEDED_ERR: QUOTA_EXCEEDED_ERR, 261 | TIMEOUT_ERR: TIMEOUT_ERR, 262 | INVALID_NODE_TYPE_ERR: INVALID_NODE_TYPE_ERR, 263 | DATA_CLONE_ERR: DATA_CLONE_ERR 264 | }; 265 | 266 | function DOMException(code) { 267 | Error.call(this); 268 | Error.captureStackTrace(this, this.constructor); 269 | this.code = code; 270 | this.message = messages[code]; 271 | this.name = names[code]; 272 | } 273 | 274 | DOMException.prototype.__proto__ = Error.prototype; // Initialize the constants on DOMException and DOMException.prototype 275 | 276 | for (var c in constants) { 277 | var v = { 278 | value: constants[c] 279 | }; 280 | Object.defineProperty(DOMException, c, v); 281 | Object.defineProperty(DOMException.prototype, c, v); 282 | } 283 | 284 | return exports$3; 285 | } 286 | 287 | var exports$4 = {}, 288 | _dewExec$4 = false; 289 | 290 | var _global = typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : global; 291 | 292 | function dew$4() { 293 | if (_dewExec$4) return exports$4; 294 | _dewExec$4 = true; 295 | 296 | /* 297 | * This file defines Domino behaviour that can be externally configured. 298 | * To change these settings, set the relevant global property *before* 299 | * you call `require("domino")`. 300 | */ 301 | exports$4.isApiWritable = !_global.__domino_frozen__; 302 | return exports$4; 303 | } 304 | 305 | var exports$5 = {}, 306 | _dewExec$5 = false; 307 | function dew$5() { 308 | if (_dewExec$5) return exports$5; 309 | _dewExec$5 = true; 310 | 311 | var DOMException = dew$3(); 312 | 313 | var ERR = DOMException; 314 | 315 | var isApiWritable = dew$4().isApiWritable; 316 | 317 | exports$5.NAMESPACE = { 318 | HTML: "http://www.w3.org/1999/xhtml", 319 | XML: "http://www.w3.org/XML/1998/namespace", 320 | XMLNS: "http://www.w3.org/2000/xmlns/", 321 | MATHML: "http://www.w3.org/1998/Math/MathML", 322 | SVG: "http://www.w3.org/2000/svg", 323 | XLINK: "http://www.w3.org/1999/xlink" 324 | }; // 325 | // Shortcut functions for throwing errors of various types. 326 | // 327 | 328 | exports$5.IndexSizeError = function () { 329 | throw new DOMException(ERR.INDEX_SIZE_ERR); 330 | }; 331 | 332 | exports$5.HierarchyRequestError = function () { 333 | throw new DOMException(ERR.HIERARCHY_REQUEST_ERR); 334 | }; 335 | 336 | exports$5.WrongDocumentError = function () { 337 | throw new DOMException(ERR.WRONG_DOCUMENT_ERR); 338 | }; 339 | 340 | exports$5.InvalidCharacterError = function () { 341 | throw new DOMException(ERR.INVALID_CHARACTER_ERR); 342 | }; 343 | 344 | exports$5.NoModificationAllowedError = function () { 345 | throw new DOMException(ERR.NO_MODIFICATION_ALLOWED_ERR); 346 | }; 347 | 348 | exports$5.NotFoundError = function () { 349 | throw new DOMException(ERR.NOT_FOUND_ERR); 350 | }; 351 | 352 | exports$5.NotSupportedError = function () { 353 | throw new DOMException(ERR.NOT_SUPPORTED_ERR); 354 | }; 355 | 356 | exports$5.InvalidStateError = function () { 357 | throw new DOMException(ERR.INVALID_STATE_ERR); 358 | }; 359 | 360 | exports$5.SyntaxError = function () { 361 | throw new DOMException(ERR.SYNTAX_ERR); 362 | }; 363 | 364 | exports$5.InvalidModificationError = function () { 365 | throw new DOMException(ERR.INVALID_MODIFICATION_ERR); 366 | }; 367 | 368 | exports$5.NamespaceError = function () { 369 | throw new DOMException(ERR.NAMESPACE_ERR); 370 | }; 371 | 372 | exports$5.InvalidAccessError = function () { 373 | throw new DOMException(ERR.INVALID_ACCESS_ERR); 374 | }; 375 | 376 | exports$5.TypeMismatchError = function () { 377 | throw new DOMException(ERR.TYPE_MISMATCH_ERR); 378 | }; 379 | 380 | exports$5.SecurityError = function () { 381 | throw new DOMException(ERR.SECURITY_ERR); 382 | }; 383 | 384 | exports$5.NetworkError = function () { 385 | throw new DOMException(ERR.NETWORK_ERR); 386 | }; 387 | 388 | exports$5.AbortError = function () { 389 | throw new DOMException(ERR.ABORT_ERR); 390 | }; 391 | 392 | exports$5.UrlMismatchError = function () { 393 | throw new DOMException(ERR.URL_MISMATCH_ERR); 394 | }; 395 | 396 | exports$5.QuotaExceededError = function () { 397 | throw new DOMException(ERR.QUOTA_EXCEEDED_ERR); 398 | }; 399 | 400 | exports$5.TimeoutError = function () { 401 | throw new DOMException(ERR.TIMEOUT_ERR); 402 | }; 403 | 404 | exports$5.InvalidNodeTypeError = function () { 405 | throw new DOMException(ERR.INVALID_NODE_TYPE_ERR); 406 | }; 407 | 408 | exports$5.DataCloneError = function () { 409 | throw new DOMException(ERR.DATA_CLONE_ERR); 410 | }; 411 | 412 | exports$5.nyi = function () { 413 | throw new Error("NotYetImplemented"); 414 | }; 415 | 416 | exports$5.shouldOverride = function () { 417 | throw new Error("Abstract function; should be overriding in subclass."); 418 | }; 419 | 420 | exports$5.assert = function (expr, msg) { 421 | if (!expr) { 422 | throw new Error("Assertion failed: " + (msg || "") + "\n" + new Error().stack); 423 | } 424 | }; 425 | 426 | exports$5.expose = function (src, c) { 427 | for (var n in src) { 428 | Object.defineProperty(c.prototype, n, { 429 | value: src[n], 430 | writable: isApiWritable 431 | }); 432 | } 433 | }; 434 | 435 | exports$5.merge = function (a, b) { 436 | for (var n in b) { 437 | a[n] = b[n]; 438 | } 439 | }; // Compare two nodes based on their document order. This function is intended 440 | // to be passed to sort(). Assumes that the array being sorted does not 441 | // contain duplicates. And that all nodes are connected and comparable. 442 | // Clever code by ppk via jeresig. 443 | 444 | 445 | exports$5.documentOrder = function (n, m) { 446 | /* jshint bitwise: false */ 447 | return 3 - (n.compareDocumentPosition(m) & 6); 448 | }; 449 | 450 | exports$5.toASCIILowerCase = function (s) { 451 | return s.replace(/[A-Z]+/g, function (c) { 452 | return c.toLowerCase(); 453 | }); 454 | }; 455 | 456 | exports$5.toASCIIUpperCase = function (s) { 457 | return s.replace(/[a-z]+/g, function (c) { 458 | return c.toUpperCase(); 459 | }); 460 | }; 461 | 462 | return exports$5; 463 | } 464 | 465 | var exports$6 = {}, 466 | _dewExec$6 = false; 467 | function dew$6() { 468 | if (_dewExec$6) return exports$6; 469 | _dewExec$6 = true; 470 | 471 | var Event = dew(); 472 | 473 | var MouseEvent = dew$2(); 474 | 475 | var utils = dew$5(); 476 | 477 | exports$6 = EventTarget; 478 | 479 | function EventTarget() { } 480 | 481 | EventTarget.prototype = { 482 | // XXX 483 | // See WebIDL В§4.8 for details on object event handlers 484 | // and how they should behave. We actually have to accept 485 | // any object to addEventListener... Can't type check it. 486 | // on registration. 487 | // XXX: 488 | // Capturing event listeners are sort of rare. I think I can optimize 489 | // them so that dispatchEvent can skip the capturing phase (or much of 490 | // it). Each time a capturing listener is added, increment a flag on 491 | // the target node and each of its ancestors. Decrement when removed. 492 | // And update the counter when nodes are added and removed from the 493 | // tree as well. Then, in dispatch event, the capturing phase can 494 | // abort if it sees any node with a zero count. 495 | addEventListener: function addEventListener(type, listener, capture) { 496 | if (!listener) return; 497 | if (capture === undefined) capture = false; 498 | if (!this._listeners) this._listeners = Object.create(null); 499 | if (!this._listeners[type]) this._listeners[type] = []; 500 | var list = this._listeners[type]; // If this listener has already been registered, just return 501 | 502 | for (var i = 0, n = list.length; i < n; i++) { 503 | var l = list[i]; 504 | if (l.listener === listener && l.capture === capture) return; 505 | } // Add an object to the list of listeners 506 | 507 | 508 | var obj = { 509 | listener: listener, 510 | capture: capture 511 | }; 512 | if (typeof listener === "function") obj.f = listener; 513 | list.push(obj); 514 | }, 515 | removeEventListener: function removeEventListener(type, listener, capture) { 516 | if (capture === undefined) capture = false; 517 | 518 | if (this._listeners) { 519 | var list = this._listeners[type]; 520 | 521 | if (list) { 522 | // Find the listener in the list and remove it 523 | for (var i = 0, n = list.length; i < n; i++) { 524 | var l = list[i]; 525 | 526 | if (l.listener === listener && l.capture === capture) { 527 | if (list.length === 1) { 528 | this._listeners[type] = undefined; 529 | } else { 530 | list.splice(i, 1); 531 | } 532 | 533 | return; 534 | } 535 | } 536 | } 537 | } 538 | }, 539 | // This is the public API for dispatching untrusted public events. 540 | // See _dispatchEvent for the implementation 541 | dispatchEvent: function dispatchEvent(event) { 542 | // Dispatch an untrusted event 543 | return this._dispatchEvent(event, false); 544 | }, 545 | // 546 | // See DOMCore В§4.4 547 | // XXX: I'll probably need another version of this method for 548 | // internal use, one that does not set isTrusted to false. 549 | // XXX: see Document._dispatchEvent: perhaps that and this could 550 | // call a common internal function with different settings of 551 | // a trusted boolean argument 552 | // 553 | // XXX: 554 | // The spec has changed in how to deal with handlers registered 555 | // on idl or content attributes rather than with addEventListener. 556 | // Used to say that they always ran first. That's how webkit does it 557 | // Spec now says that they run in a position determined by 558 | // when they were first set. FF does it that way. See: 559 | // http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#event-handlers 560 | // 561 | _dispatchEvent: function _dispatchEvent(event, trusted) { 562 | if (typeof trusted !== "boolean") trusted = false; 563 | 564 | function invoke(target, event) { 565 | var type = event.type, 566 | phase = event.eventPhase; 567 | event.currentTarget = target; // If there was an individual handler defined, invoke it first 568 | // XXX: see comment above: this shouldn't always be first. 569 | 570 | if (phase !== Event.CAPTURING_PHASE && target._handlers && target._handlers[type]) { 571 | var handler = target._handlers[type]; 572 | var rv; 573 | 574 | if (typeof handler === "function") { 575 | rv = handler.call(event.currentTarget, event); 576 | } else { 577 | var f = handler.handleEvent; 578 | if (typeof f !== "function") throw new TypeError("handleEvent property of " + "event handler object is" + "not a function."); 579 | rv = f.call(handler, event); 580 | } 581 | 582 | switch (event.type) { 583 | case "mouseover": 584 | if (rv === true) // Historical baggage 585 | event.preventDefault(); 586 | break; 587 | 588 | case "beforeunload": // XXX: eventually we need a special case here 589 | 590 | /* falls through */ 591 | 592 | default: 593 | if (rv === false) event.preventDefault(); 594 | break; 595 | } 596 | } // Now invoke list list of listeners for this target and type 597 | 598 | 599 | var list = target._listeners && target._listeners[type]; 600 | if (!list) return; 601 | list = list.slice(); 602 | 603 | for (var i = 0, n = list.length; i < n; i++) { 604 | if (event._immediatePropagationStopped) return; 605 | var l = list[i]; 606 | if (phase === Event.CAPTURING_PHASE && !l.capture || phase === Event.BUBBLING_PHASE && l.capture) continue; 607 | 608 | if (l.f) { 609 | l.f.call(event.currentTarget, event); 610 | } else { 611 | var fn = l.listener.handleEvent; 612 | if (typeof fn !== "function") throw new TypeError("handleEvent property of event listener object is not a function."); 613 | fn.call(l.listener, event); 614 | } 615 | } 616 | } 617 | 618 | if (!event._initialized || event._dispatching) utils.InvalidStateError(); 619 | event.isTrusted = trusted; // Begin dispatching the event now 620 | 621 | event._dispatching = true; 622 | event.target = this; // Build the list of targets for the capturing and bubbling phases 623 | // XXX: we'll eventually have to add Window to this list. 624 | 625 | var ancestors = []; 626 | 627 | for (var n = this.parentNode; n; n = n.parentNode) ancestors.push(n); // Capturing phase 628 | 629 | 630 | event.eventPhase = Event.CAPTURING_PHASE; 631 | 632 | for (var i = ancestors.length - 1; i >= 0; i--) { 633 | invoke(ancestors[i], event); 634 | if (event._propagationStopped) break; 635 | } // At target phase 636 | 637 | 638 | if (!event._propagationStopped) { 639 | event.eventPhase = Event.AT_TARGET; 640 | invoke(this, event); 641 | } // Bubbling phase 642 | 643 | 644 | if (event.bubbles && !event._propagationStopped) { 645 | event.eventPhase = Event.BUBBLING_PHASE; 646 | 647 | for (var ii = 0, nn = ancestors.length; ii < nn; ii++) { 648 | invoke(ancestors[ii], event); 649 | if (event._propagationStopped) break; 650 | } 651 | } 652 | 653 | event._dispatching = false; 654 | event.eventPhase = Event.AT_TARGET; 655 | event.currentTarget = null; // Deal with mouse events and figure out when 656 | // a click has happened 657 | 658 | if (trusted && !event.defaultPrevented && event instanceof MouseEvent) { 659 | switch (event.type) { 660 | case "mousedown": 661 | this._armed = { 662 | x: event.clientX, 663 | y: event.clientY, 664 | t: event.timeStamp 665 | }; 666 | break; 667 | 668 | case "mouseout": 669 | case "mouseover": 670 | this._armed = null; 671 | break; 672 | 673 | case "mouseup": 674 | if (this._isClick(event)) this._doClick(event); 675 | this._armed = null; 676 | break; 677 | } 678 | } 679 | 680 | return !event.defaultPrevented; 681 | }, 682 | // Determine whether a click occurred 683 | // XXX We don't support double clicks for now 684 | _isClick: function (event) { 685 | return this._armed !== null && event.type === "mouseup" && event.isTrusted && event.button === 0 && event.timeStamp - this._armed.t < 1000 && Math.abs(event.clientX - this._armed.x) < 10 && Math.abs(event.clientY - this._armed.Y) < 10; 686 | }, 687 | // Clicks are handled like this: 688 | // http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#interactive-content-0 689 | // 690 | // Note that this method is similar to the HTMLElement.click() method 691 | // The event argument must be the trusted mouseup event 692 | _doClick: function (event) { 693 | if (this._click_in_progress) return; 694 | this._click_in_progress = true; // Find the nearest enclosing element that is activatable 695 | // An element is activatable if it has a 696 | // _post_click_activation_steps hook 697 | 698 | var activated = this; 699 | 700 | while (activated && !activated._post_click_activation_steps) activated = activated.parentNode; 701 | 702 | if (activated && activated._pre_click_activation_steps) { 703 | activated._pre_click_activation_steps(); 704 | } 705 | 706 | var click = this.ownerDocument.createEvent("MouseEvent"); 707 | click.initMouseEvent("click", true, true, this.ownerDocument.defaultView, 1, event.screenX, event.screenY, event.clientX, event.clientY, event.ctrlKey, event.altKey, event.shiftKey, event.metaKey, event.button, null); 708 | 709 | var result = this._dispatchEvent(click, true); 710 | 711 | if (activated) { 712 | if (result) { 713 | // This is where hyperlinks get followed, for example. 714 | if (activated._post_click_activation_steps) activated._post_click_activation_steps(click); 715 | } else { 716 | if (activated._cancelled_activation_steps) activated._cancelled_activation_steps(); 717 | } 718 | } 719 | }, 720 | // 721 | // An event handler is like an event listener, but it registered 722 | // by setting an IDL or content attribute like onload or onclick. 723 | // There can only be one of these at a time for any event type. 724 | // This is an internal method for the attribute accessors and 725 | // content attribute handlers that need to register events handlers. 726 | // The type argument is the same as in addEventListener(). 727 | // The handler argument is the same as listeners in addEventListener: 728 | // it can be a function or an object. Pass null to remove any existing 729 | // handler. Handlers are always invoked before any listeners of 730 | // the same type. They are not invoked during the capturing phase 731 | // of event dispatch. 732 | // 733 | _setEventHandler: function _setEventHandler(type, handler) { 734 | if (!this._handlers) this._handlers = Object.create(null); 735 | this._handlers[type] = handler; 736 | }, 737 | _getEventHandler: function _getEventHandler(type) { 738 | return this._handlers && this._handlers[type] || null; 739 | } 740 | }; 741 | return exports$6; 742 | } 743 | 744 | var exports$7 = {}, 745 | _dewExec$7 = false; 746 | function dew$7() { 747 | if (_dewExec$7) return exports$7; 748 | _dewExec$7 = true; 749 | 750 | var utils = dew$5(); 751 | 752 | var LinkedList = exports$7 = { 753 | // basic validity tests on a circular linked list a 754 | valid: function (a) { 755 | utils.assert(a, "list falsy"); 756 | utils.assert(a._previousSibling, "previous falsy"); 757 | utils.assert(a._nextSibling, "next falsy"); // xxx check that list is actually circular 758 | 759 | return true; 760 | }, 761 | // insert a before b 762 | insertBefore: function (a, b) { 763 | utils.assert(LinkedList.valid(a) && LinkedList.valid(b)); 764 | var a_first = a, 765 | a_last = a._previousSibling; 766 | var b_first = b, 767 | b_last = b._previousSibling; 768 | a_first._previousSibling = b_last; 769 | a_last._nextSibling = b_first; 770 | b_last._nextSibling = a_first; 771 | b_first._previousSibling = a_last; 772 | utils.assert(LinkedList.valid(a) && LinkedList.valid(b)); 773 | }, 774 | // replace a single node a with a list b (which could be null) 775 | replace: function (a, b) { 776 | utils.assert(LinkedList.valid(a) && (b === null || LinkedList.valid(b))); 777 | 778 | if (b !== null) { 779 | LinkedList.insertBefore(b, a); 780 | } 781 | 782 | LinkedList.remove(a); 783 | utils.assert(LinkedList.valid(a) && (b === null || LinkedList.valid(b))); 784 | }, 785 | // remove single node a from its list 786 | remove: function (a) { 787 | utils.assert(LinkedList.valid(a)); 788 | var prev = a._previousSibling; 789 | 790 | if (prev === a) { 791 | return; 792 | } 793 | 794 | var next = a._nextSibling; 795 | prev._nextSibling = next; 796 | next._previousSibling = prev; 797 | a._previousSibling = a._nextSibling = a; 798 | utils.assert(LinkedList.valid(a)); 799 | } 800 | }; 801 | return exports$7; 802 | } 803 | 804 | var exports$8 = {}, 805 | _dewExec$8 = false; 806 | function dew$8() { 807 | if (_dewExec$8) return exports$8; 808 | _dewExec$8 = true; 809 | exports$8 = { 810 | // NOTE: The `serializeOne()` function used to live on the `Node.prototype` 811 | // as a private method `Node#_serializeOne(child)`, however that requires 812 | // a megamorphic property access `this._serializeOne` just to get to the 813 | // method, and this is being done on lots of different `Node` subclasses, 814 | // which puts a lot of pressure on V8's megamorphic stub cache. So by 815 | // moving the helper off of the `Node.prototype` and into a separate 816 | // function in this helper module, we get a monomorphic property access 817 | // `NodeUtils.serializeOne` to get to the function and reduce pressure 818 | // on the megamorphic stub cache. 819 | // See https://github.com/fgnass/domino/pull/142 for more information. 820 | serializeOne: serializeOne 821 | }; 822 | 823 | var utils = dew$5(); 824 | 825 | var NAMESPACE = utils.NAMESPACE; 826 | var hasRawContent = { 827 | STYLE: true, 828 | SCRIPT: true, 829 | XMP: true, 830 | IFRAME: true, 831 | NOEMBED: true, 832 | NOFRAMES: true, 833 | PLAINTEXT: true 834 | }; 835 | var emptyElements = { 836 | area: true, 837 | base: true, 838 | basefont: true, 839 | bgsound: true, 840 | br: true, 841 | col: true, 842 | embed: true, 843 | frame: true, 844 | hr: true, 845 | img: true, 846 | input: true, 847 | keygen: true, 848 | link: true, 849 | meta: true, 850 | param: true, 851 | source: true, 852 | track: true, 853 | wbr: true 854 | }; 855 | var extraNewLine = { 856 | /* Removed in https://github.com/whatwg/html/issues/944 857 | pre: true, 858 | textarea: true, 859 | listing: true 860 | */ 861 | }; 862 | 863 | function escape(s) { 864 | return s.replace(/[&<>\u00A0]/g, function (c) { 865 | switch (c) { 866 | case "&": 867 | return "&"; 868 | 869 | case "<": 870 | return "<"; 871 | 872 | case ">": 873 | return ">"; 874 | 875 | case "\xA0": 876 | return " "; 877 | } 878 | }); 879 | } 880 | 881 | function escapeAttr(s) { 882 | var toEscape = /[&"\u00A0]/g; 883 | 884 | if (!toEscape.test(s)) { 885 | // nothing to do, fast path 886 | return s; 887 | } else { 888 | return s.replace(toEscape, function (c) { 889 | switch (c) { 890 | case "&": 891 | return "&"; 892 | 893 | case "\"": 894 | return """; 895 | 896 | case "\xA0": 897 | return " "; 898 | } 899 | }); 900 | } 901 | } 902 | 903 | function attrname(a) { 904 | var ns = a.namespaceURI; 905 | if (!ns) return a.localName; 906 | if (ns === NAMESPACE.XML) return "xml:" + a.localName; 907 | if (ns === NAMESPACE.XLINK) return "xlink:" + a.localName; 908 | 909 | if (ns === NAMESPACE.XMLNS) { 910 | if (a.localName === "xmlns") return "xmlns"; else return "xmlns:" + a.localName; 911 | } 912 | 913 | return a.name; 914 | } 915 | 916 | function serializeOne(kid, parent) { 917 | var s = ""; 918 | 919 | switch (kid.nodeType) { 920 | case 1: 921 | //ELEMENT_NODE 922 | var ns = kid.namespaceURI; 923 | var html = ns === NAMESPACE.HTML; 924 | var tagname = html || ns === NAMESPACE.SVG || ns === NAMESPACE.MATHML ? kid.localName : kid.tagName; 925 | s += "<" + tagname; 926 | 927 | for (var j = 0, k = kid._numattrs; j < k; j++) { 928 | var a = kid._attr(j); 929 | 930 | s += " " + attrname(a); 931 | if (a.value !== undefined) s += "=\"" + escapeAttr(a.value) + "\""; 932 | } 933 | 934 | s += ">"; 935 | 936 | if (!(html && emptyElements[tagname])) { 937 | var ss = kid.serialize(); 938 | if (html && extraNewLine[tagname] && ss.charAt(0) === "\n") s += "\n"; // Serialize children and add end tag for all others 939 | 940 | s += ss; 941 | s += ""; 942 | } 943 | 944 | break; 945 | 946 | case 3: //TEXT_NODE 947 | 948 | case 4: 949 | //CDATA_SECTION_NODE 950 | var parenttag; 951 | if (parent.nodeType === 1 952 | /*ELEMENT_NODE*/ 953 | && parent.namespaceURI === NAMESPACE.HTML) parenttag = parent.tagName; else parenttag = ""; 954 | 955 | if (hasRawContent[parenttag] || parenttag === "NOSCRIPT" && parent.ownerDocument._scripting_enabled) { 956 | s += kid.data; 957 | } else { 958 | s += escape(kid.data); 959 | } 960 | 961 | break; 962 | 963 | case 8: 964 | //COMMENT_NODE 965 | s += ""; 966 | break; 967 | 968 | case 7: 969 | //PROCESSING_INSTRUCTION_NODE 970 | s += ""; 971 | break; 972 | 973 | case 10: 974 | //DOCUMENT_TYPE_NODE 975 | s += ""; 989 | break; 990 | 991 | default: 992 | utils.InvalidStateError(); 993 | } 994 | 995 | return s; 996 | } 997 | 998 | return exports$8; 999 | } 1000 | 1001 | var exports$9 = {}, 1002 | _dewExec$9 = false; 1003 | function dew$9() { 1004 | if (_dewExec$9) return exports$9; 1005 | _dewExec$9 = true; 1006 | exports$9 = Node; 1007 | 1008 | var EventTarget = dew$6(); 1009 | 1010 | var LinkedList = dew$7(); 1011 | 1012 | var NodeUtils = dew$8(); 1013 | 1014 | var utils = dew$5(); // All nodes have a nodeType and an ownerDocument. 1015 | // Once inserted, they also have a parentNode. 1016 | // This is an abstract class; all nodes in a document are instances 1017 | // of a subtype, so all the properties are defined by more specific 1018 | // constructors. 1019 | 1020 | 1021 | function Node() { 1022 | EventTarget.call(this); 1023 | this.parentNode = null; 1024 | this._nextSibling = this._previousSibling = this; 1025 | this._index = undefined; 1026 | } 1027 | 1028 | var ELEMENT_NODE = Node.ELEMENT_NODE = 1; 1029 | var ATTRIBUTE_NODE = Node.ATTRIBUTE_NODE = 2; 1030 | var TEXT_NODE = Node.TEXT_NODE = 3; 1031 | var CDATA_SECTION_NODE = Node.CDATA_SECTION_NODE = 4; 1032 | var ENTITY_REFERENCE_NODE = Node.ENTITY_REFERENCE_NODE = 5; 1033 | var ENTITY_NODE = Node.ENTITY_NODE = 6; 1034 | var PROCESSING_INSTRUCTION_NODE = Node.PROCESSING_INSTRUCTION_NODE = 7; 1035 | var COMMENT_NODE = Node.COMMENT_NODE = 8; 1036 | var DOCUMENT_NODE = Node.DOCUMENT_NODE = 9; 1037 | var DOCUMENT_TYPE_NODE = Node.DOCUMENT_TYPE_NODE = 10; 1038 | var DOCUMENT_FRAGMENT_NODE = Node.DOCUMENT_FRAGMENT_NODE = 11; 1039 | var NOTATION_NODE = Node.NOTATION_NODE = 12; 1040 | var DOCUMENT_POSITION_DISCONNECTED = Node.DOCUMENT_POSITION_DISCONNECTED = 1; 1041 | var DOCUMENT_POSITION_PRECEDING = Node.DOCUMENT_POSITION_PRECEDING = 2; 1042 | var DOCUMENT_POSITION_FOLLOWING = Node.DOCUMENT_POSITION_FOLLOWING = 4; 1043 | var DOCUMENT_POSITION_CONTAINS = Node.DOCUMENT_POSITION_CONTAINS = 8; 1044 | var DOCUMENT_POSITION_CONTAINED_BY = Node.DOCUMENT_POSITION_CONTAINED_BY = 16; 1045 | var DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 32; 1046 | Node.prototype = Object.create(EventTarget.prototype, { 1047 | // Node that are not inserted into the tree inherit a null parent 1048 | // XXX: the baseURI attribute is defined by dom core, but 1049 | // a correct implementation of it requires HTML features, so 1050 | // we'll come back to this later. 1051 | baseURI: { 1052 | get: utils.nyi 1053 | }, 1054 | parentElement: { 1055 | get: function () { 1056 | return this.parentNode && this.parentNode.nodeType === ELEMENT_NODE ? this.parentNode : null; 1057 | } 1058 | }, 1059 | hasChildNodes: { 1060 | value: utils.shouldOverride 1061 | }, 1062 | firstChild: { 1063 | get: utils.shouldOverride 1064 | }, 1065 | lastChild: { 1066 | get: utils.shouldOverride 1067 | }, 1068 | previousSibling: { 1069 | get: function () { 1070 | var parent = this.parentNode; 1071 | if (!parent) return null; 1072 | if (this === parent.firstChild) return null; 1073 | return this._previousSibling; 1074 | } 1075 | }, 1076 | nextSibling: { 1077 | get: function () { 1078 | var parent = this.parentNode, 1079 | next = this._nextSibling; 1080 | if (!parent) return null; 1081 | if (next === parent.firstChild) return null; 1082 | return next; 1083 | } 1084 | }, 1085 | textContent: { 1086 | // Should override for DocumentFragment/Element/Attr/Text/PI/Comment 1087 | get: function () { 1088 | return null; 1089 | }, 1090 | set: function (v) { 1091 | /* do nothing */ 1092 | } 1093 | }, 1094 | _countChildrenOfType: { 1095 | value: function (type) { 1096 | var sum = 0; 1097 | 1098 | for (var kid = this.firstChild; kid !== null; kid = kid.nextSibling) { 1099 | if (kid.nodeType === type) sum++; 1100 | } 1101 | 1102 | return sum; 1103 | } 1104 | }, 1105 | _ensureInsertValid: { 1106 | value: function _ensureInsertValid(node, child, isPreinsert) { 1107 | var parent = this, 1108 | i, 1109 | kid; 1110 | if (!node.nodeType) throw new TypeError("not a node"); // 1. If parent is not a Document, DocumentFragment, or Element 1111 | // node, throw a HierarchyRequestError. 1112 | 1113 | switch (parent.nodeType) { 1114 | case DOCUMENT_NODE: 1115 | case DOCUMENT_FRAGMENT_NODE: 1116 | case ELEMENT_NODE: 1117 | break; 1118 | 1119 | default: 1120 | utils.HierarchyRequestError(); 1121 | } // 2. If node is a host-including inclusive ancestor of parent, 1122 | // throw a HierarchyRequestError. 1123 | 1124 | 1125 | if (node.isAncestor(parent)) utils.HierarchyRequestError(); // 3. If child is not null and its parent is not parent, then 1126 | // throw a NotFoundError. (replaceChild omits the 'child is not null' 1127 | // and throws a TypeError here if child is null.) 1128 | 1129 | if (child !== null || !isPreinsert) { 1130 | if (child.parentNode !== parent) utils.NotFoundError(); 1131 | } // 4. If node is not a DocumentFragment, DocumentType, Element, 1132 | // Text, ProcessingInstruction, or Comment node, throw a 1133 | // HierarchyRequestError. 1134 | 1135 | 1136 | switch (node.nodeType) { 1137 | case DOCUMENT_FRAGMENT_NODE: 1138 | case DOCUMENT_TYPE_NODE: 1139 | case ELEMENT_NODE: 1140 | case TEXT_NODE: 1141 | case PROCESSING_INSTRUCTION_NODE: 1142 | case COMMENT_NODE: 1143 | break; 1144 | 1145 | default: 1146 | utils.HierarchyRequestError(); 1147 | } // 5. If either node is a Text node and parent is a document, or 1148 | // node is a doctype and parent is not a document, throw a 1149 | // HierarchyRequestError. 1150 | // 6. If parent is a document, and any of the statements below, switched 1151 | // on node, are true, throw a HierarchyRequestError. 1152 | 1153 | 1154 | if (parent.nodeType === DOCUMENT_NODE) { 1155 | switch (node.nodeType) { 1156 | case TEXT_NODE: 1157 | utils.HierarchyRequestError(); 1158 | break; 1159 | 1160 | case DOCUMENT_FRAGMENT_NODE: 1161 | // 6a1. If node has more than one element child or has a Text 1162 | // node child. 1163 | if (node._countChildrenOfType(TEXT_NODE) > 0) utils.HierarchyRequestError(); 1164 | 1165 | switch (node._countChildrenOfType(ELEMENT_NODE)) { 1166 | case 0: 1167 | break; 1168 | 1169 | case 1: 1170 | // 6a2. Otherwise, if node has one element child and either 1171 | // parent has an element child, child is a doctype, or child 1172 | // is not null and a doctype is following child. [preinsert] 1173 | // 6a2. Otherwise, if node has one element child and either 1174 | // parent has an element child that is not child or a 1175 | // doctype is following child. [replaceWith] 1176 | if (child !== null 1177 | /* always true here for replaceWith */ 1178 | ) { 1179 | if (isPreinsert && child.nodeType === DOCUMENT_TYPE_NODE) utils.HierarchyRequestError(); 1180 | 1181 | for (kid = child.nextSibling; kid !== null; kid = kid.nextSibling) { 1182 | if (kid.nodeType === DOCUMENT_TYPE_NODE) utils.HierarchyRequestError(); 1183 | } 1184 | } 1185 | 1186 | i = parent._countChildrenOfType(ELEMENT_NODE); 1187 | 1188 | if (isPreinsert) { 1189 | // "parent has an element child" 1190 | if (i > 0) utils.HierarchyRequestError(); 1191 | } else { 1192 | // "parent has an element child that is not child" 1193 | if (i > 1 || i === 1 && child.nodeType !== ELEMENT_NODE) utils.HierarchyRequestError(); 1194 | } 1195 | 1196 | break; 1197 | 1198 | default: 1199 | // 6a1, continued. (more than one Element child) 1200 | utils.HierarchyRequestError(); 1201 | } 1202 | 1203 | break; 1204 | 1205 | case ELEMENT_NODE: 1206 | // 6b. parent has an element child, child is a doctype, or 1207 | // child is not null and a doctype is following child. [preinsert] 1208 | // 6b. parent has an element child that is not child or a 1209 | // doctype is following child. [replaceWith] 1210 | if (child !== null 1211 | /* always true here for replaceWith */ 1212 | ) { 1213 | if (isPreinsert && child.nodeType === DOCUMENT_TYPE_NODE) utils.HierarchyRequestError(); 1214 | 1215 | for (kid = child.nextSibling; kid !== null; kid = kid.nextSibling) { 1216 | if (kid.nodeType === DOCUMENT_TYPE_NODE) utils.HierarchyRequestError(); 1217 | } 1218 | } 1219 | 1220 | i = parent._countChildrenOfType(ELEMENT_NODE); 1221 | 1222 | if (isPreinsert) { 1223 | // "parent has an element child" 1224 | if (i > 0) utils.HierarchyRequestError(); 1225 | } else { 1226 | // "parent has an element child that is not child" 1227 | if (i > 1 || i === 1 && child.nodeType !== ELEMENT_NODE) utils.HierarchyRequestError(); 1228 | } 1229 | 1230 | break; 1231 | 1232 | case DOCUMENT_TYPE_NODE: 1233 | // 6c. parent has a doctype child, child is non-null and an 1234 | // element is preceding child, or child is null and parent has 1235 | // an element child. [preinsert] 1236 | // 6c. parent has a doctype child that is not child, or an 1237 | // element is preceding child. [replaceWith] 1238 | if (child === null) { 1239 | if (parent._countChildrenOfType(ELEMENT_NODE)) utils.HierarchyRequestError(); 1240 | } else { 1241 | // child is always non-null for [replaceWith] case 1242 | for (kid = parent.firstChild; kid !== null; kid = kid.nextSibling) { 1243 | if (kid === child) break; 1244 | if (kid.nodeType === ELEMENT_NODE) utils.HierarchyRequestError(); 1245 | } 1246 | } 1247 | 1248 | i = parent._countChildrenOfType(DOCUMENT_TYPE_NODE); 1249 | 1250 | if (isPreinsert) { 1251 | // "parent has an doctype child" 1252 | if (i > 0) utils.HierarchyRequestError(); 1253 | } else { 1254 | // "parent has an doctype child that is not child" 1255 | if (i > 1 || i === 1 && child.nodeType !== DOCUMENT_TYPE_NODE) utils.HierarchyRequestError(); 1256 | } 1257 | 1258 | break; 1259 | } 1260 | } else { 1261 | // 5, continued: (parent is not a document) 1262 | if (node.nodeType === DOCUMENT_TYPE_NODE) utils.HierarchyRequestError(); 1263 | } 1264 | } 1265 | }, 1266 | insertBefore: { 1267 | value: function insertBefore(node, child) { 1268 | var parent = this; // 1. Ensure pre-insertion validity 1269 | 1270 | parent._ensureInsertValid(node, child, true); // 2. Let reference child be child. 1271 | 1272 | 1273 | var refChild = child; // 3. If reference child is node, set it to node's next sibling 1274 | 1275 | if (refChild === node) { 1276 | refChild = node.nextSibling; 1277 | } // 4. Adopt node into parent's node document. 1278 | 1279 | 1280 | parent.doc.adoptNode(node); // 5. Insert node into parent before reference child. 1281 | 1282 | node._insertOrReplace(parent, refChild, false); // 6. Return node 1283 | 1284 | 1285 | return node; 1286 | } 1287 | }, 1288 | appendChild: { 1289 | value: function (child) { 1290 | // This invokes _appendChild after doing validity checks. 1291 | return this.insertBefore(child, null); 1292 | } 1293 | }, 1294 | _appendChild: { 1295 | value: function (child) { 1296 | child._insertOrReplace(this, null, false); 1297 | } 1298 | }, 1299 | removeChild: { 1300 | value: function removeChild(child) { 1301 | var parent = this; 1302 | if (!child.nodeType) throw new TypeError("not a node"); 1303 | if (child.parentNode !== parent) utils.NotFoundError(); 1304 | child.remove(); 1305 | return child; 1306 | } 1307 | }, 1308 | // To replace a `child` with `node` within a `parent` (this) 1309 | replaceChild: { 1310 | value: function replaceChild(node, child) { 1311 | var parent = this; // Ensure validity (slight differences from pre-insertion check) 1312 | 1313 | parent._ensureInsertValid(node, child, false); // Adopt node into parent's node document. 1314 | 1315 | 1316 | if (node.doc !== parent.doc) { 1317 | // XXX adoptNode has side-effect of removing node from its parent 1318 | // and generating a mutation event, thus causing the _insertOrReplace 1319 | // to generate two deletes and an insert instead of a 'move' 1320 | // event. It looks like the new MutationObserver stuff avoids 1321 | // this problem, but for now let's only adopt (ie, remove `node` 1322 | // from its parent) here if we need to. 1323 | parent.doc.adoptNode(node); 1324 | } // Do the replace. 1325 | 1326 | 1327 | node._insertOrReplace(parent, child, true); 1328 | 1329 | return child; 1330 | } 1331 | }, 1332 | // See: http://ejohn.org/blog/comparing-document-position/ 1333 | contains: { 1334 | value: function contains(node) { 1335 | if (node === null) { 1336 | return false; 1337 | } 1338 | 1339 | if (this === node) { 1340 | return true; 1341 | /* inclusive descendant */ 1342 | } 1343 | /* jshint bitwise: false */ 1344 | 1345 | 1346 | return (this.compareDocumentPosition(node) & DOCUMENT_POSITION_CONTAINED_BY) !== 0; 1347 | } 1348 | }, 1349 | compareDocumentPosition: { 1350 | value: function compareDocumentPosition(that) { 1351 | // Basic algorithm for finding the relative position of two nodes. 1352 | // Make a list the ancestors of each node, starting with the 1353 | // document element and proceeding down to the nodes themselves. 1354 | // Then, loop through the lists, looking for the first element 1355 | // that differs. The order of those two elements give the 1356 | // order of their descendant nodes. Or, if one list is a prefix 1357 | // of the other one, then that node contains the other. 1358 | if (this === that) return 0; // If they're not owned by the same document or if one is rooted 1359 | // and one is not, then they're disconnected. 1360 | 1361 | if (this.doc !== that.doc || this.rooted !== that.rooted) return DOCUMENT_POSITION_DISCONNECTED + DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; // Get arrays of ancestors for this and that 1362 | 1363 | var these = [], 1364 | those = []; 1365 | 1366 | for (var n = this; n !== null; n = n.parentNode) these.push(n); 1367 | 1368 | for (n = that; n !== null; n = n.parentNode) those.push(n); 1369 | 1370 | these.reverse(); // So we start with the outermost 1371 | 1372 | those.reverse(); 1373 | if (these[0] !== those[0]) // No common ancestor 1374 | return DOCUMENT_POSITION_DISCONNECTED + DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; 1375 | n = Math.min(these.length, those.length); 1376 | 1377 | for (var i = 1; i < n; i++) { 1378 | if (these[i] !== those[i]) { 1379 | // We found two different ancestors, so compare 1380 | // their positions 1381 | if (these[i].index < those[i].index) return DOCUMENT_POSITION_FOLLOWING; else return DOCUMENT_POSITION_PRECEDING; 1382 | } 1383 | } // If we get to here, then one of the nodes (the one with the 1384 | // shorter list of ancestors) contains the other one. 1385 | 1386 | 1387 | if (these.length < those.length) return DOCUMENT_POSITION_FOLLOWING + DOCUMENT_POSITION_CONTAINED_BY; else return DOCUMENT_POSITION_PRECEDING + DOCUMENT_POSITION_CONTAINS; 1388 | } 1389 | }, 1390 | isSameNode: { 1391 | value: function isSameNode(node) { 1392 | return this === node; 1393 | } 1394 | }, 1395 | // This method implements the generic parts of node equality testing 1396 | // and defers to the (non-recursive) type-specific isEqual() method 1397 | // defined by subclasses 1398 | isEqualNode: { 1399 | value: function isEqualNode(node) { 1400 | if (!node) return false; 1401 | if (node.nodeType !== this.nodeType) return false; // Check type-specific properties for equality 1402 | 1403 | if (!this.isEqual(node)) return false; // Now check children for number and equality 1404 | 1405 | for (var c1 = this.firstChild, c2 = node.firstChild; c1 && c2; c1 = c1.nextSibling, c2 = c2.nextSibling) { 1406 | if (!c1.isEqualNode(c2)) return false; 1407 | } 1408 | 1409 | return c1 === null && c2 === null; 1410 | } 1411 | }, 1412 | // This method delegates shallow cloning to a clone() method 1413 | // that each concrete subclass must implement 1414 | cloneNode: { 1415 | value: function (deep) { 1416 | // Clone this node 1417 | var clone = this.clone(); // Handle the recursive case if necessary 1418 | 1419 | if (deep) { 1420 | for (var kid = this.firstChild; kid !== null; kid = kid.nextSibling) { 1421 | clone._appendChild(kid.cloneNode(true)); 1422 | } 1423 | } 1424 | 1425 | return clone; 1426 | } 1427 | }, 1428 | lookupPrefix: { 1429 | value: function lookupPrefix(ns) { 1430 | var e; 1431 | if (ns === "" || ns === null || ns === undefined) return null; 1432 | 1433 | switch (this.nodeType) { 1434 | case ELEMENT_NODE: 1435 | return this._lookupNamespacePrefix(ns, this); 1436 | 1437 | case DOCUMENT_NODE: 1438 | e = this.documentElement; 1439 | return e ? e.lookupPrefix(ns) : null; 1440 | 1441 | case ENTITY_NODE: 1442 | case NOTATION_NODE: 1443 | case DOCUMENT_FRAGMENT_NODE: 1444 | case DOCUMENT_TYPE_NODE: 1445 | return null; 1446 | 1447 | case ATTRIBUTE_NODE: 1448 | e = this.ownerElement; 1449 | return e ? e.lookupPrefix(ns) : null; 1450 | 1451 | default: 1452 | e = this.parentElement; 1453 | return e ? e.lookupPrefix(ns) : null; 1454 | } 1455 | } 1456 | }, 1457 | lookupNamespaceURI: { 1458 | value: function lookupNamespaceURI(prefix) { 1459 | if (prefix === "" || prefix === undefined) { 1460 | prefix = null; 1461 | } 1462 | 1463 | var e; 1464 | 1465 | switch (this.nodeType) { 1466 | case ELEMENT_NODE: 1467 | return utils.shouldOverride(); 1468 | 1469 | case DOCUMENT_NODE: 1470 | e = this.documentElement; 1471 | return e ? e.lookupNamespaceURI(prefix) : null; 1472 | 1473 | case ENTITY_NODE: 1474 | case NOTATION_NODE: 1475 | case DOCUMENT_TYPE_NODE: 1476 | case DOCUMENT_FRAGMENT_NODE: 1477 | return null; 1478 | 1479 | case ATTRIBUTE_NODE: 1480 | e = this.ownerElement; 1481 | return e ? e.lookupNamespaceURI(prefix) : null; 1482 | 1483 | default: 1484 | e = this.parentElement; 1485 | return e ? e.lookupNamespaceURI(prefix) : null; 1486 | } 1487 | } 1488 | }, 1489 | isDefaultNamespace: { 1490 | value: function isDefaultNamespace(ns) { 1491 | if (ns === "" || ns === undefined) { 1492 | ns = null; 1493 | } 1494 | 1495 | var defaultNamespace = this.lookupNamespaceURI(null); 1496 | return defaultNamespace === ns; 1497 | } 1498 | }, 1499 | // Utility methods for nodes. Not part of the DOM 1500 | // Return the index of this node in its parent. 1501 | // Throw if no parent, or if this node is not a child of its parent 1502 | index: { 1503 | get: function () { 1504 | var parent = this.parentNode; 1505 | if (this === parent.firstChild) return 0; // fast case 1506 | 1507 | var kids = parent.childNodes; 1508 | 1509 | if (this._index === undefined || kids[this._index] !== this) { 1510 | // Ensure that we don't have an O(N^2) blowup if none of the 1511 | // kids have defined indices yet and we're traversing via 1512 | // nextSibling or previousSibling 1513 | for (var i = 0; i < kids.length; i++) { 1514 | kids[i]._index = i; 1515 | } 1516 | 1517 | utils.assert(kids[this._index] === this); 1518 | } 1519 | 1520 | return this._index; 1521 | } 1522 | }, 1523 | // Return true if this node is equal to or is an ancestor of that node 1524 | // Note that nodes are considered to be ancestors of themselves 1525 | isAncestor: { 1526 | value: function (that) { 1527 | // If they belong to different documents, then they're unrelated. 1528 | if (this.doc !== that.doc) return false; // If one is rooted and one isn't then they're not related 1529 | 1530 | if (this.rooted !== that.rooted) return false; // Otherwise check by traversing the parentNode chain 1531 | 1532 | for (var e = that; e; e = e.parentNode) { 1533 | if (e === this) return true; 1534 | } 1535 | 1536 | return false; 1537 | } 1538 | }, 1539 | // DOMINO Changed the behavior to conform with the specs. See: 1540 | // https://groups.google.com/d/topic/mozilla.dev.platform/77sIYcpdDmc/discussion 1541 | ensureSameDoc: { 1542 | value: function (that) { 1543 | if (that.ownerDocument === null) { 1544 | that.ownerDocument = this.doc; 1545 | } else if (that.ownerDocument !== this.doc) { 1546 | utils.WrongDocumentError(); 1547 | } 1548 | } 1549 | }, 1550 | removeChildren: { 1551 | value: utils.shouldOverride 1552 | }, 1553 | // Insert this node as a child of parent before the specified child, 1554 | // or insert as the last child of parent if specified child is null, 1555 | // or replace the specified child with this node, firing mutation events as 1556 | // necessary 1557 | _insertOrReplace: { 1558 | value: function _insertOrReplace(parent, before, isReplace) { 1559 | var child = this, 1560 | before_index, 1561 | i; 1562 | 1563 | if (child.nodeType === DOCUMENT_FRAGMENT_NODE && child.rooted) { 1564 | utils.HierarchyRequestError(); 1565 | } 1566 | /* Ensure index of `before` is cached before we (possibly) remove it. */ 1567 | 1568 | 1569 | if (parent._childNodes) { 1570 | before_index = before === null ? parent._childNodes.length : before.index; 1571 | /* ensure _index is cached */ 1572 | // If we are already a child of the specified parent, then 1573 | // the index may have to be adjusted. 1574 | 1575 | if (child.parentNode === parent) { 1576 | var child_index = child.index; // If the child is before the spot it is to be inserted at, 1577 | // then when it is removed, the index of that spot will be 1578 | // reduced. 1579 | 1580 | if (child_index < before_index) { 1581 | before_index--; 1582 | } 1583 | } 1584 | } // Delete the old child 1585 | 1586 | 1587 | if (isReplace) { 1588 | if (before.rooted) before.doc.mutateRemove(before); 1589 | before.parentNode = null; 1590 | } 1591 | 1592 | var n = before; 1593 | 1594 | if (n === null) { 1595 | n = parent.firstChild; 1596 | } // If both the child and the parent are rooted, then we want to 1597 | // transplant the child without uprooting and rerooting it. 1598 | 1599 | 1600 | var bothRooted = child.rooted && parent.rooted; 1601 | 1602 | if (child.nodeType === DOCUMENT_FRAGMENT_NODE) { 1603 | var spliceArgs = [0, isReplace ? 1 : 0], 1604 | next; 1605 | 1606 | for (var kid = child.firstChild; kid !== null; kid = next) { 1607 | next = kid.nextSibling; 1608 | spliceArgs.push(kid); 1609 | kid.parentNode = parent; 1610 | } 1611 | 1612 | var len = spliceArgs.length; // Add all nodes to the new parent, overwriting the old child 1613 | 1614 | if (isReplace) { 1615 | LinkedList.replace(n, len > 2 ? spliceArgs[2] : null); 1616 | } else if (len > 2 && n !== null) { 1617 | LinkedList.insertBefore(spliceArgs[2], n); 1618 | } 1619 | 1620 | if (parent._childNodes) { 1621 | spliceArgs[0] = before === null ? parent._childNodes.length : before._index; 1622 | 1623 | parent._childNodes.splice.apply(parent._childNodes, spliceArgs); 1624 | 1625 | for (i = 2; i < len; i++) { 1626 | spliceArgs[i]._index = spliceArgs[0] + (i - 2); 1627 | } 1628 | } else if (parent._firstChild === before) { 1629 | if (len > 2) { 1630 | parent._firstChild = spliceArgs[2]; 1631 | } else if (isReplace) { 1632 | parent._firstChild = null; 1633 | } 1634 | } // Remove all nodes from the document fragment 1635 | 1636 | 1637 | if (child._childNodes) { 1638 | child._childNodes.length = 0; 1639 | } else { 1640 | child._firstChild = null; 1641 | } // Call the mutation handlers 1642 | // Use spliceArgs since the original array has been destroyed. The 1643 | // liveness guarantee requires us to clone the array so that 1644 | // references to the childNodes of the DocumentFragment will be empty 1645 | // when the insertion handlers are called. 1646 | 1647 | 1648 | if (parent.rooted) { 1649 | parent.modify(); 1650 | 1651 | for (i = 2; i < len; i++) { 1652 | parent.doc.mutateInsert(spliceArgs[i]); 1653 | } 1654 | } 1655 | } else { 1656 | if (before === child) { 1657 | return; 1658 | } 1659 | 1660 | if (bothRooted) { 1661 | // Remove the child from its current position in the tree 1662 | // without calling remove(), since we don't want to uproot it. 1663 | child._remove(); 1664 | } else if (child.parentNode) { 1665 | child.remove(); 1666 | } // Insert it as a child of its new parent 1667 | 1668 | 1669 | child.parentNode = parent; 1670 | 1671 | if (isReplace) { 1672 | LinkedList.replace(n, child); 1673 | 1674 | if (parent._childNodes) { 1675 | child._index = before_index; 1676 | parent._childNodes[before_index] = child; 1677 | } else if (parent._firstChild === before) { 1678 | parent._firstChild = child; 1679 | } 1680 | } else { 1681 | if (n !== null) { 1682 | LinkedList.insertBefore(child, n); 1683 | } 1684 | 1685 | if (parent._childNodes) { 1686 | child._index = before_index; 1687 | 1688 | parent._childNodes.splice(before_index, 0, child); 1689 | } else if (parent._firstChild === before) { 1690 | parent._firstChild = child; 1691 | } 1692 | } 1693 | 1694 | if (bothRooted) { 1695 | parent.modify(); // Generate a move mutation event 1696 | 1697 | parent.doc.mutateMove(child); 1698 | } else if (parent.rooted) { 1699 | parent.modify(); 1700 | parent.doc.mutateInsert(child); 1701 | } 1702 | } 1703 | } 1704 | }, 1705 | // Return the lastModTime value for this node. (For use as a 1706 | // cache invalidation mechanism. If the node does not already 1707 | // have one, initialize it from the owner document's modclock 1708 | // property. (Note that modclock does not return the actual 1709 | // time; it is simply a counter incremented on each document 1710 | // modification) 1711 | lastModTime: { 1712 | get: function () { 1713 | if (!this._lastModTime) { 1714 | this._lastModTime = this.doc.modclock; 1715 | } 1716 | 1717 | return this._lastModTime; 1718 | } 1719 | }, 1720 | // Increment the owner document's modclock and use the new 1721 | // value to update the lastModTime value for this node and 1722 | // all of its ancestors. Nodes that have never had their 1723 | // lastModTime value queried do not need to have a 1724 | // lastModTime property set on them since there is no 1725 | // previously queried value to ever compare the new value 1726 | // against, so only update nodes that already have a 1727 | // _lastModTime property. 1728 | modify: { 1729 | value: function () { 1730 | if (this.doc.modclock) { 1731 | // Skip while doc.modclock == 0 1732 | var time = ++this.doc.modclock; 1733 | 1734 | for (var n = this; n; n = n.parentElement) { 1735 | if (n._lastModTime) { 1736 | n._lastModTime = time; 1737 | } 1738 | } 1739 | } 1740 | } 1741 | }, 1742 | // This attribute is not part of the DOM but is quite helpful. 1743 | // It returns the document with which a node is associated. Usually 1744 | // this is the ownerDocument. But ownerDocument is null for the 1745 | // document object itself, so this is a handy way to get the document 1746 | // regardless of the node type 1747 | doc: { 1748 | get: function () { 1749 | return this.ownerDocument || this; 1750 | } 1751 | }, 1752 | // If the node has a nid (node id), then it is rooted in a document 1753 | rooted: { 1754 | get: function () { 1755 | return !!this._nid; 1756 | } 1757 | }, 1758 | normalize: { 1759 | value: function () { 1760 | var next; 1761 | 1762 | for (var child = this.firstChild; child !== null; child = next) { 1763 | next = child.nextSibling; 1764 | 1765 | if (child.normalize) { 1766 | child.normalize(); 1767 | } 1768 | 1769 | if (child.nodeType !== Node.TEXT_NODE) { 1770 | continue; 1771 | } 1772 | 1773 | if (child.nodeValue === "") { 1774 | this.removeChild(child); 1775 | continue; 1776 | } 1777 | 1778 | var prevChild = child.previousSibling; 1779 | 1780 | if (prevChild === null) { 1781 | continue; 1782 | } else if (prevChild.nodeType === Node.TEXT_NODE) { 1783 | // merge this with previous and remove the child 1784 | prevChild.appendData(child.nodeValue); 1785 | this.removeChild(child); 1786 | } 1787 | } 1788 | } 1789 | }, 1790 | // Convert the children of a node to an HTML string. 1791 | // This is used by the innerHTML getter 1792 | // The serialization spec is at: 1793 | // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments 1794 | // 1795 | // The serialization logic is intentionally implemented in a separate 1796 | // `NodeUtils` helper instead of the more obvious choice of a private 1797 | // `_serializeOne()` method on the `Node.prototype` in order to avoid 1798 | // the megamorphic `this._serializeOne` property access, which reduces 1799 | // performance unnecessarily. If you need specialized behavior for a 1800 | // certain subclass, you'll need to implement that in `NodeUtils`. 1801 | // See https://github.com/fgnass/domino/pull/142 for more information. 1802 | serialize: { 1803 | value: function () { 1804 | var s = ""; 1805 | 1806 | for (var kid = this.firstChild; kid !== null; kid = kid.nextSibling) { 1807 | s += NodeUtils.serializeOne(kid, this); 1808 | } 1809 | 1810 | return s; 1811 | } 1812 | }, 1813 | // Non-standard, but often useful for debugging. 1814 | outerHTML: { 1815 | get: function () { 1816 | return NodeUtils.serializeOne(this, { 1817 | nodeType: 0 1818 | }); 1819 | }, 1820 | set: utils.nyi 1821 | }, 1822 | // mirror node type properties in the prototype, so they are present 1823 | // in instances of Node (and subclasses) 1824 | ELEMENT_NODE: { 1825 | value: ELEMENT_NODE 1826 | }, 1827 | ATTRIBUTE_NODE: { 1828 | value: ATTRIBUTE_NODE 1829 | }, 1830 | TEXT_NODE: { 1831 | value: TEXT_NODE 1832 | }, 1833 | CDATA_SECTION_NODE: { 1834 | value: CDATA_SECTION_NODE 1835 | }, 1836 | ENTITY_REFERENCE_NODE: { 1837 | value: ENTITY_REFERENCE_NODE 1838 | }, 1839 | ENTITY_NODE: { 1840 | value: ENTITY_NODE 1841 | }, 1842 | PROCESSING_INSTRUCTION_NODE: { 1843 | value: PROCESSING_INSTRUCTION_NODE 1844 | }, 1845 | COMMENT_NODE: { 1846 | value: COMMENT_NODE 1847 | }, 1848 | DOCUMENT_NODE: { 1849 | value: DOCUMENT_NODE 1850 | }, 1851 | DOCUMENT_TYPE_NODE: { 1852 | value: DOCUMENT_TYPE_NODE 1853 | }, 1854 | DOCUMENT_FRAGMENT_NODE: { 1855 | value: DOCUMENT_FRAGMENT_NODE 1856 | }, 1857 | NOTATION_NODE: { 1858 | value: NOTATION_NODE 1859 | }, 1860 | DOCUMENT_POSITION_DISCONNECTED: { 1861 | value: DOCUMENT_POSITION_DISCONNECTED 1862 | }, 1863 | DOCUMENT_POSITION_PRECEDING: { 1864 | value: DOCUMENT_POSITION_PRECEDING 1865 | }, 1866 | DOCUMENT_POSITION_FOLLOWING: { 1867 | value: DOCUMENT_POSITION_FOLLOWING 1868 | }, 1869 | DOCUMENT_POSITION_CONTAINS: { 1870 | value: DOCUMENT_POSITION_CONTAINS 1871 | }, 1872 | DOCUMENT_POSITION_CONTAINED_BY: { 1873 | value: DOCUMENT_POSITION_CONTAINED_BY 1874 | }, 1875 | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: { 1876 | value: DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC 1877 | } 1878 | }); 1879 | return exports$9; 1880 | } 1881 | 1882 | export { dew$5 as a, dew$7 as b, dew$8 as c, dew$9 as d, dew$3 as e, dew as f, dew$1 as g, dew$2 as h, dew$4 as i, dew$6 as j }; 1883 | 1884 | //# sourceMappingURL=74f7187c.js.map -------------------------------------------------------------------------------- /engine.ts: -------------------------------------------------------------------------------- 1 | 2 | import { NgModuleFactory, CompilerFactory, Compiler } from 'https://jspm.dev/@angular/core@11'; 3 | import { INITIAL_CONFIG, renderModuleFactory } from './platform-server.mjs'; 4 | const { readFile } = Deno; 5 | const decoder = new TextDecoder(); 6 | 7 | export class CommonEngine { 8 | 9 | /** Return an instance of the platformServer compiler */ 10 | 11 | // @ts-ignore 12 | getCompiler(): Compiler { 13 | // @ts-ignore 14 | const compilerFactory: CompilerFactory = this.compilerFactory;//platformCoreDynamic().injector.get(CompilerFactory); 15 | 16 | return compilerFactory.createCompiler(); 17 | } 18 | 19 | private factoryCacheMap = new Map(); 20 | private readonly templateCache: Map = new Map() 21 | 22 | // @ts-ignore 23 | constructor(private compilerFactory: CompilerFactory, private moduleOrFactory?: any, 24 | private providers: any[] = []) { } 25 | 26 | /** 27 | * Render an HTML document for a specific URL with specified 28 | * render options 29 | */ 30 | async render(opts: any): Promise { 31 | // if opts.document dosen't exist then opts.documentFilePath must 32 | const doc = opts.document || await this.getDocument(opts.documentFilePath as string); 33 | const extraProviders = [ 34 | ...(opts.providers || []), 35 | ...(this.providers || []), 36 | { 37 | provide: INITIAL_CONFIG, 38 | useValue: { 39 | document: doc, 40 | url: opts.url 41 | } 42 | } 43 | ]; 44 | 45 | const moduleOrFactory = this.moduleOrFactory || opts.bootstrap; 46 | const factory = await this.getFactory(moduleOrFactory); 47 | 48 | return renderModuleFactory(factory, { extraProviders }); 49 | } 50 | 51 | /** Return the factory for a given engine instance */ 52 | async getFactory(moduleOrFactory: any): Promise { 53 | // If module has been compiled AoT 54 | if (moduleOrFactory instanceof NgModuleFactory) { 55 | return moduleOrFactory; 56 | } else { 57 | // we're in JIT mode 58 | const moduleFactory = this.factoryCacheMap.get(moduleOrFactory); 59 | 60 | // If module factory is cached 61 | if (moduleFactory) { 62 | return moduleFactory; 63 | } 64 | 65 | // Compile the module and cache it 66 | const factory = await this.getCompiler().compileModuleAsync(moduleOrFactory); 67 | this.factoryCacheMap.set(moduleOrFactory, factory); 68 | 69 | return factory; 70 | } 71 | } 72 | 73 | /** Retrieve the document from the cache or the filesystem */ 74 | private getDocument(filePath: string): Promise { 75 | if (this.templateCache.has(filePath)) { 76 | return Promise.resolve(this.templateCache.get(filePath) + ''); 77 | } 78 | 79 | return readFile(filePath).then(source => { 80 | const template: string = decoder.decode(source) 81 | this.templateCache.set(filePath, template) 82 | 83 | return template; 84 | }); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | ## Run as server: 2 | 3 | deno run --importmap=importmap.json --location=https://jspm.dev --allow-read 4 | server.ts 5 | 6 | Open in browser: https://localhost:8000 7 | 8 | ## Render app page 9 | 10 | deno run --importmap=importmap.json --location=https://jspm.dev --allow-read 11 | main.ts 12 | 13 | Output: 14 | 15 | ```html 16 | 17 | 18 | Angular SSR with Deno 19 | 22 | 23 | 24 | 25 | Angular in Deno v1.8.0 26 | 27 | 28 | ``` 29 | -------------------------------------------------------------------------------- /example/app.component.css: -------------------------------------------------------------------------------- 1 | my-app{ 2 | color: green; 3 | } -------------------------------------------------------------------------------- /example/app.component.html: -------------------------------------------------------------------------------- 1 | Angular in Deno v{{versionDeno}} -------------------------------------------------------------------------------- /example/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | 3 | @Component({ 4 | selector: "my-app", 5 | templateUrl: "./app.component.html", 6 | styleUrls: ["./app.component.css"], 7 | }) 8 | export class AppComponent { 9 | versionDeno = Deno.version.deno; 10 | } 11 | -------------------------------------------------------------------------------- /example/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from "@angular/core"; 2 | import { ServerModule } from "../mod.ts"; 3 | import { AppComponent } from "./app.component.ts"; 4 | 5 | @NgModule({ 6 | imports: [ServerModule], 7 | declarations: [AppComponent], 8 | bootstrap: [AppComponent], 9 | providers: [], 10 | }) 11 | export class AppModule {} 12 | -------------------------------------------------------------------------------- /example/importmap.json: -------------------------------------------------------------------------------- 1 | { 2 | "imports": { 3 | "@angular/core": "https://jspm.dev/@angular/core@12.0.3", 4 | "zone.js": "https://jspm.dev/zone.js/dist/zone", 5 | "reflect": "https://deno.land/x/alosaur@v0.34.0/src/injection/reflect.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Angular SSR with Deno 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/main.test.ts: -------------------------------------------------------------------------------- 1 | import { CompilerFactory, enableProdMode } from "@angular/core"; 2 | import { bootstrap, CommonEngine } from "../mod.ts"; 3 | import { AppModule } from "./app.module.ts"; 4 | import "reflect"; 5 | import "zone.js"; 6 | 7 | import { assert } from "https://deno.land/std@0.97.0/testing/asserts.ts"; 8 | 9 | /** 10 | * Test cases 11 | */ 12 | Deno.test({ 13 | name: "Should render text with Angular version text", 14 | async fn(): Promise { 15 | const { readFile } = Deno; 16 | const decoder = new TextDecoder(); 17 | 18 | const indexHtml = decoder.decode(await readFile("index.html")); 19 | 20 | enableProdMode(); 21 | 22 | const ref: any = await bootstrap(AppModule, indexHtml); 23 | 24 | const engine = new CommonEngine( 25 | ref.injector.get(CompilerFactory), 26 | AppModule, 27 | ); 28 | 29 | const text: string = await engine.render({ document: indexHtml, url: "/" }); 30 | 31 | assert(text.includes("Angular SSR with Deno")); 32 | assert(text.includes('ng-version="12.0.3"')); 33 | }, 34 | }); 35 | -------------------------------------------------------------------------------- /example/main.ts: -------------------------------------------------------------------------------- 1 | import { CompilerFactory, enableProdMode } from "@angular/core"; 2 | import { bootstrap, CommonEngine } from "../mod.ts"; 3 | import { AppModule } from "./app.module.ts"; 4 | 5 | import "reflect"; 6 | import "zone.js"; 7 | 8 | const { readFile } = Deno; 9 | const decoder = new TextDecoder(); 10 | 11 | const indexHtml = decoder.decode(await readFile("index.html")); 12 | 13 | enableProdMode(); 14 | 15 | const ref: any = await bootstrap(AppModule, indexHtml); 16 | 17 | export const engine = new CommonEngine( 18 | ref.injector.get(CompilerFactory), 19 | AppModule, 20 | ); 21 | 22 | // Render page 23 | 24 | console.log(await engine.render({ document: indexHtml, url: "/" })); 25 | -------------------------------------------------------------------------------- /example/server.ts: -------------------------------------------------------------------------------- 1 | import { serve } from "https://deno.land/std@0.89.0/http/server.ts"; 2 | 3 | import { CompilerFactory, enableProdMode } from "@angular/core"; 4 | import { bootstrap, CommonEngine } from "../mod.ts"; 5 | import { AppModule } from "./app.module.ts"; 6 | 7 | import "reflect"; 8 | import "zone.js"; 9 | 10 | const { readFile } = Deno; 11 | const decoder = new TextDecoder(); 12 | 13 | const indexHtml = decoder.decode(await readFile("index.html")); 14 | 15 | enableProdMode(); 16 | 17 | const ref: any = await bootstrap(AppModule, indexHtml); 18 | 19 | export const engine = new CommonEngine( 20 | ref.injector.get(CompilerFactory), 21 | AppModule, 22 | ); 23 | 24 | const s = serve({ port: 8000 }); 25 | 26 | for await (const req of s) { 27 | const body: string = await engine.render( 28 | { document: indexHtml, url: req.url }, 29 | ); 30 | req.respond({ body }); 31 | } 32 | -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "experimentalDecorators": true, 4 | "emitDecoratorMetadata": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /mod.ts: -------------------------------------------------------------------------------- 1 | export { CommonEngine } from './engine.ts'; 2 | 3 | export { bootstrap, RESOURCE_PATH } from './bootstrap.ts'; 4 | 5 | export { ServerModule } from './platform-server.mjs'; 6 | -------------------------------------------------------------------------------- /platform-server.mjs: -------------------------------------------------------------------------------- 1 | import * as _common2 from 'https://jspm.dev/npm:@angular/common@12.0.3!cjs'; 2 | import * as _core2 from 'https://jspm.dev/npm:@angular/core@12.0.3!cjs'; 3 | import * as _platformBrowser2 from 'https://jspm.dev/npm:@angular/platform-browser@12.0.3!cjs'; 4 | import * as _browser2 from 'https://jspm.dev/npm:@angular/animations@12.0.3/browser!cjs'; 5 | import * as _http2 from 'https://jspm.dev/npm:@angular/common@12.0.3/http!cjs'; 6 | import * as _platformBrowserDynamic2 from 'https://jspm.dev/npm:@angular/platform-browser-dynamic@12.0.3!cjs'; 7 | import * as _animations2 from 'https://jspm.dev/npm:@angular/platform-browser@12.0.3/animations!cjs'; 8 | import * as _rxjs2 from 'https://jspm.dev/npm:rxjs!cjs'; 9 | import * as _url2 from 'https://jspm.dev/npm:@jspm/core@2/nodelibs/url'; 10 | import * as _compiler2 from 'https://jspm.dev/npm:@angular/compiler@12.0.3!cjs'; 11 | import * as _operators2 from 'https://jspm.dev/npm:rxjs/operators!cjs'; 12 | import * as _domino2 from './domino/domino.mjs'; 13 | 14 | import XMLHttpRequest from "https://deno.land/x/xmlhttprequest_deno@v0.0.2/mod.js"; 15 | 16 | var _xhr = XMLHttpRequest; 17 | 18 | var _common = "default" in _common2 ? _common2.default : _common2; 19 | 20 | var _core = "default" in _core2 ? _core2.default : _core2; 21 | 22 | var _platformBrowser = "default" in _platformBrowser2 ? _platformBrowser2.default : _platformBrowser2; 23 | 24 | var _browser = "default" in _browser2 ? _browser2.default : _browser2; 25 | 26 | var _http = "default" in _http2 ? _http2.default : _http2; 27 | 28 | var _platformBrowserDynamic = "default" in _platformBrowserDynamic2 ? _platformBrowserDynamic2.default : _platformBrowserDynamic2; 29 | 30 | var _animations = "default" in _animations2 ? _animations2.default : _animations2; 31 | 32 | var _rxjs = "default" in _rxjs2 ? _rxjs2.default : _rxjs2; 33 | 34 | var _url = "default" in _url2 ? _url2.default : _url2; 35 | 36 | var _compiler = "default" in _compiler2 ? _compiler2.default : _compiler2; 37 | 38 | var _operators = "default" in _operators2 ? _operators2.default : _operators2; 39 | 40 | var _domino = "default" in _domino2 ? _domino2.default : _domino2; 41 | 42 | 43 | 44 | var _global = typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : global; 45 | 46 | var exports = {}; 47 | 48 | /** 49 | * @license Angular v12.0.3 50 | * (c) 2010-2021 Google LLC. https://angular.io/ 51 | * License: MIT 52 | */ 53 | (function (global, factory) { 54 | factory(exports, _common, _core, _platformBrowser, _browser, _http, _platformBrowserDynamic, _animations, _rxjs, _url, _compiler, _operators); 55 | })(exports, function (exports, common, core, platformBrowser, browser, http, platformBrowserDynamic, animations, rxjs, url, compiler, operators) { 56 | 'use strict'; 57 | /*! ***************************************************************************** 58 | Copyright (c) Microsoft Corporation. 59 | Permission to use, copy, modify, and/or distribute this software for any 60 | purpose with or without fee is hereby granted. 61 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 62 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 63 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 64 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 65 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 66 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 67 | PERFORMANCE OF THIS SOFTWARE. 68 | ***************************************************************************** */ 69 | 70 | /* global Reflect, Promise */ 71 | 72 | var extendStatics = function (d, b) { 73 | extendStatics = Object.setPrototypeOf || { 74 | __proto__: [] 75 | } instanceof Array && function (d, b) { 76 | d.__proto__ = b; 77 | } || function (d, b) { 78 | for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; 79 | }; 80 | 81 | return extendStatics(d, b); 82 | }; 83 | 84 | function __extends(d, b) { 85 | if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); 86 | extendStatics(d, b); 87 | 88 | function __() { 89 | (this || _global).constructor = d; 90 | } 91 | 92 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 93 | } 94 | 95 | var __assign = function () { 96 | __assign = Object.assign || function __assign(t) { 97 | for (var s, i = 1, n = arguments.length; i < n; i++) { 98 | s = arguments[i]; 99 | 100 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 101 | } 102 | 103 | return t; 104 | }; 105 | 106 | return __assign.apply(this || _global, arguments); 107 | }; 108 | 109 | function __rest(s, e) { 110 | var t = {}; 111 | 112 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; 113 | 114 | if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { 115 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; 116 | } 117 | return t; 118 | } 119 | 120 | function __decorate(decorators, target, key, desc) { 121 | var c = arguments.length, 122 | r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, 123 | d; 124 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 125 | return c > 3 && r && Object.defineProperty(target, key, r), r; 126 | } 127 | 128 | function __param(paramIndex, decorator) { 129 | return function (target, key) { 130 | decorator(target, key, paramIndex); 131 | }; 132 | } 133 | 134 | function __metadata(metadataKey, metadataValue) { 135 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); 136 | } 137 | 138 | function __awaiter(thisArg, _arguments, P, generator) { 139 | function adopt(value) { 140 | return value instanceof P ? value : new P(function (resolve) { 141 | resolve(value); 142 | }); 143 | } 144 | 145 | return new (P || (P = Promise))(function (resolve, reject) { 146 | function fulfilled(value) { 147 | try { 148 | step(generator.next(value)); 149 | } catch (e) { 150 | reject(e); 151 | } 152 | } 153 | 154 | function rejected(value) { 155 | try { 156 | step(generator["throw"](value)); 157 | } catch (e) { 158 | reject(e); 159 | } 160 | } 161 | 162 | function step(result) { 163 | result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); 164 | } 165 | 166 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 167 | }); 168 | } 169 | 170 | function __generator(thisArg, body) { 171 | var _ = { 172 | label: 0, 173 | sent: function () { 174 | if (t[0] & 1) throw t[1]; 175 | return t[1]; 176 | }, 177 | trys: [], 178 | ops: [] 179 | }, 180 | f, 181 | y, 182 | t, 183 | g; 184 | return g = { 185 | next: verb(0), 186 | "throw": verb(1), 187 | "return": verb(2) 188 | }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { 189 | return this || _global; 190 | }), g; 191 | 192 | function verb(n) { 193 | return function (v) { 194 | return step([n, v]); 195 | }; 196 | } 197 | 198 | function step(op) { 199 | if (f) throw new TypeError("Generator is already executing."); 200 | 201 | while (_) try { 202 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; 203 | if (y = 0, t) op = [op[0] & 2, t.value]; 204 | 205 | switch (op[0]) { 206 | case 0: 207 | case 1: 208 | t = op; 209 | break; 210 | 211 | case 4: 212 | _.label++; 213 | return { 214 | value: op[1], 215 | done: false 216 | }; 217 | 218 | case 5: 219 | _.label++; 220 | y = op[1]; 221 | op = [0]; 222 | continue; 223 | 224 | case 7: 225 | op = _.ops.pop(); 226 | 227 | _.trys.pop(); 228 | 229 | continue; 230 | 231 | default: 232 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { 233 | _ = 0; 234 | continue; 235 | } 236 | 237 | if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) { 238 | _.label = op[1]; 239 | break; 240 | } 241 | 242 | if (op[0] === 6 && _.label < t[1]) { 243 | _.label = t[1]; 244 | t = op; 245 | break; 246 | } 247 | 248 | if (t && _.label < t[2]) { 249 | _.label = t[2]; 250 | 251 | _.ops.push(op); 252 | 253 | break; 254 | } 255 | 256 | if (t[2]) _.ops.pop(); 257 | 258 | _.trys.pop(); 259 | 260 | continue; 261 | } 262 | 263 | op = body.call(thisArg, _); 264 | } catch (e) { 265 | op = [6, e]; 266 | y = 0; 267 | } finally { 268 | f = t = 0; 269 | } 270 | 271 | if (op[0] & 5) throw op[1]; 272 | return { 273 | value: op[0] ? op[1] : void 0, 274 | done: true 275 | }; 276 | } 277 | } 278 | 279 | var __createBinding = Object.create ? function (o, m, k, k2) { 280 | if (k2 === undefined) k2 = k; 281 | Object.defineProperty(o, k2, { 282 | enumerable: true, 283 | get: function () { 284 | return m[k]; 285 | } 286 | }); 287 | } : function (o, m, k, k2) { 288 | if (k2 === undefined) k2 = k; 289 | o[k2] = m[k]; 290 | }; 291 | 292 | function __exportStar(m, o) { 293 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p); 294 | } 295 | 296 | function __values(o) { 297 | var s = typeof Symbol === "function" && Symbol.iterator, 298 | m = s && o[s], 299 | i = 0; 300 | if (m) return m.call(o); 301 | if (o && typeof o.length === "number") return { 302 | next: function () { 303 | if (o && i >= o.length) o = void 0; 304 | return { 305 | value: o && o[i++], 306 | done: !o 307 | }; 308 | } 309 | }; 310 | throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); 311 | } 312 | 313 | function __read(o, n) { 314 | var m = typeof Symbol === "function" && o[Symbol.iterator]; 315 | if (!m) return o; 316 | var i = m.call(o), 317 | r, 318 | ar = [], 319 | e; 320 | 321 | try { 322 | while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); 323 | } catch (error) { 324 | e = { 325 | error: error 326 | }; 327 | } finally { 328 | try { 329 | if (r && !r.done && (m = i["return"])) m.call(i); 330 | } finally { 331 | if (e) throw e.error; 332 | } 333 | } 334 | 335 | return ar; 336 | } 337 | /** @deprecated */ 338 | 339 | 340 | function __spread() { 341 | for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); 342 | 343 | return ar; 344 | } 345 | /** @deprecated */ 346 | 347 | 348 | function __spreadArrays() { 349 | for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; 350 | 351 | for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; 352 | 353 | return r; 354 | } 355 | 356 | function __spreadArray(to, from) { 357 | for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) to[j] = from[i]; 358 | 359 | return to; 360 | } 361 | 362 | function __await(v) { 363 | return (this || _global) instanceof __await ? ((this || _global).v = v, this || _global) : new __await(v); 364 | } 365 | 366 | function __asyncGenerator(thisArg, _arguments, generator) { 367 | if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); 368 | var g = generator.apply(thisArg, _arguments || []), 369 | i, 370 | q = []; 371 | return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { 372 | return this || _global; 373 | }, i; 374 | 375 | function verb(n) { 376 | if (g[n]) i[n] = function (v) { 377 | return new Promise(function (a, b) { 378 | q.push([n, v, a, b]) > 1 || resume(n, v); 379 | }); 380 | }; 381 | } 382 | 383 | function resume(n, v) { 384 | try { 385 | step(g[n](v)); 386 | } catch (e) { 387 | settle(q[0][3], e); 388 | } 389 | } 390 | 391 | function step(r) { 392 | r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); 393 | } 394 | 395 | function fulfill(value) { 396 | resume("next", value); 397 | } 398 | 399 | function reject(value) { 400 | resume("throw", value); 401 | } 402 | 403 | function settle(f, v) { 404 | if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); 405 | } 406 | } 407 | 408 | function __asyncDelegator(o) { 409 | var i, p; 410 | return i = {}, verb("next"), verb("throw", function (e) { 411 | throw e; 412 | }), verb("return"), i[Symbol.iterator] = function () { 413 | return this || _global; 414 | }, i; 415 | 416 | function verb(n, f) { 417 | i[n] = o[n] ? function (v) { 418 | return (p = !p) ? { 419 | value: __await(o[n](v)), 420 | done: n === "return" 421 | } : f ? f(v) : v; 422 | } : f; 423 | } 424 | } 425 | 426 | function __asyncValues(o) { 427 | if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); 428 | var m = o[Symbol.asyncIterator], 429 | i; 430 | return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { 431 | return this || _global; 432 | }, i); 433 | 434 | function verb(n) { 435 | i[n] = o[n] && function (v) { 436 | return new Promise(function (resolve, reject) { 437 | v = o[n](v), settle(resolve, reject, v.done, v.value); 438 | }); 439 | }; 440 | } 441 | 442 | function settle(resolve, reject, d, v) { 443 | Promise.resolve(v).then(function (v) { 444 | resolve({ 445 | value: v, 446 | done: d 447 | }); 448 | }, reject); 449 | } 450 | } 451 | 452 | function __makeTemplateObject(cooked, raw) { 453 | if (Object.defineProperty) { 454 | Object.defineProperty(cooked, "raw", { 455 | value: raw 456 | }); 457 | } else { 458 | cooked.raw = raw; 459 | } 460 | 461 | return cooked; 462 | } 463 | 464 | ; 465 | 466 | var __setModuleDefault = Object.create ? function (o, v) { 467 | Object.defineProperty(o, "default", { 468 | enumerable: true, 469 | value: v 470 | }); 471 | } : function (o, v) { 472 | o["default"] = v; 473 | }; 474 | 475 | function __importStar(mod) { 476 | if (mod && mod.__esModule) return mod; 477 | var result = {}; 478 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 479 | 480 | __setModuleDefault(result, mod); 481 | 482 | return result; 483 | } 484 | 485 | function __importDefault(mod) { 486 | return mod && mod.__esModule ? mod : { 487 | default: mod 488 | }; 489 | } 490 | 491 | function __classPrivateFieldGet(receiver, state, kind, f) { 492 | if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); 493 | if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); 494 | return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); 495 | } 496 | 497 | function __classPrivateFieldSet(receiver, state, value, kind, f) { 498 | if (kind === "m") throw new TypeError("Private method is not writable"); 499 | if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); 500 | if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); 501 | return kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value), value; 502 | } 503 | /** 504 | * @license 505 | * Copyright Google LLC All Rights Reserved. 506 | * 507 | * Use of this source code is governed by an MIT-style license that can be 508 | * found in the LICENSE file at https://angular.io/license 509 | */ 510 | 511 | 512 | var domino = _domino; 513 | 514 | function setDomTypes() { 515 | // Make all Domino types available in the global env. 516 | Object.assign(_global, domino.impl); 517 | _global["KeyboardEvent"] = domino.impl.Event; 518 | } 519 | /** 520 | * Parses a document string to a Document object. 521 | */ 522 | 523 | 524 | function parseDocument(html, url) { 525 | if (url === void 0) { 526 | url = "/"; 527 | } 528 | 529 | var window = domino.createWindow(html, url); 530 | var doc = window.document; 531 | return doc; 532 | } 533 | /** 534 | * Serializes a document to string. 535 | */ 536 | 537 | 538 | function serializeDocument(doc) { 539 | return doc.serialize(); 540 | } 541 | /** 542 | * DOM Adapter for the server platform based on https://github.com/fgnass/domino. 543 | */ 544 | 545 | 546 | var DominoAdapter = 547 | /** @class */ 548 | function (_super) { 549 | __extends(DominoAdapter, _super); 550 | 551 | function DominoAdapter() { 552 | var _this = _super.apply(this || _global, __spreadArray([], __read(arguments))) || this || _global; 553 | 554 | _this.supportsDOMEvents = false; 555 | return _this; 556 | } 557 | 558 | DominoAdapter.makeCurrent = function () { 559 | setDomTypes(); 560 | common.ɵsetRootDomAdapter(new DominoAdapter()); 561 | }; 562 | 563 | DominoAdapter.prototype.createHtmlDocument = function () { 564 | return parseDocument("fakeTitle"); 565 | }; 566 | 567 | DominoAdapter.prototype.getDefaultDocument = function () { 568 | if (!DominoAdapter.defaultDoc) { 569 | DominoAdapter.defaultDoc = domino.createDocument(); 570 | } 571 | 572 | return DominoAdapter.defaultDoc; 573 | }; 574 | 575 | DominoAdapter.prototype.isElementNode = function (node) { 576 | return node ? node.nodeType === DominoAdapter.defaultDoc.ELEMENT_NODE : false; 577 | }; 578 | 579 | DominoAdapter.prototype.isShadowRoot = function (node) { 580 | return node.shadowRoot == node; 581 | }; 582 | /** @deprecated No longer being used in Ivy code. To be removed in version 14. */ 583 | 584 | 585 | DominoAdapter.prototype.getGlobalEventTarget = function (doc, target) { 586 | if (target === "window") { 587 | return doc.defaultView; 588 | } 589 | 590 | if (target === "document") { 591 | return doc; 592 | } 593 | 594 | if (target === "body") { 595 | return doc.body; 596 | } 597 | 598 | return null; 599 | }; 600 | 601 | DominoAdapter.prototype.getBaseHref = function (doc) { 602 | var _a; // TODO(alxhub): Need relative path logic from BrowserDomAdapter here? 603 | 604 | 605 | return ((_a = doc.documentElement.querySelector("base")) === null || _a === void 0 ? void 0 : _a.getAttribute("href")) || ""; 606 | }; 607 | 608 | DominoAdapter.prototype.dispatchEvent = function (el, evt) { 609 | el.dispatchEvent(evt); // Dispatch the event to the window also. 610 | 611 | var doc = el.ownerDocument || el; 612 | var win = doc.defaultView; 613 | 614 | if (win) { 615 | win.dispatchEvent(evt); 616 | } 617 | }; 618 | 619 | DominoAdapter.prototype.getUserAgent = function () { 620 | return "Fake user agent"; 621 | }; 622 | 623 | DominoAdapter.prototype.getCookie = function (name) { 624 | throw new Error("getCookie has not been implemented"); 625 | }; 626 | 627 | return DominoAdapter; 628 | }(platformBrowser.ɵBrowserDomAdapter); 629 | /** 630 | * @license 631 | * Copyright Google LLC All Rights Reserved. 632 | * 633 | * Use of this source code is governed by an MIT-style license that can be 634 | * found in the LICENSE file at https://angular.io/license 635 | */ 636 | 637 | /** 638 | * Representation of the current platform state. 639 | * 640 | * @publicApi 641 | */ 642 | 643 | 644 | var PlatformState = 645 | /** @class */ 646 | function () { 647 | function PlatformState(_doc) { 648 | (this || _global)._doc = _doc; 649 | } 650 | /** 651 | * Renders the current state of the platform to string. 652 | */ 653 | 654 | 655 | PlatformState.prototype.renderToString = function () { 656 | return serializeDocument((this || _global)._doc); 657 | }; 658 | /** 659 | * Returns the current DOM state. 660 | */ 661 | 662 | 663 | PlatformState.prototype.getDocument = function () { 664 | return (this || _global)._doc; 665 | }; 666 | 667 | return PlatformState; 668 | }(); 669 | 670 | PlatformState.decorators = [{ 671 | type: core.Injectable 672 | }]; 673 | 674 | PlatformState.ctorParameters = function () { 675 | return [{ 676 | type: undefined, 677 | decorators: [{ 678 | type: core.Inject, 679 | args: [common.DOCUMENT] 680 | }] 681 | }]; 682 | }; 683 | /** 684 | * @license 685 | * Copyright Google LLC All Rights Reserved. 686 | * 687 | * Use of this source code is governed by an MIT-style license that can be 688 | * found in the LICENSE file at https://angular.io/license 689 | */ 690 | 691 | /** 692 | * The DI token for setting the initial config for the platform. 693 | * 694 | * @publicApi 695 | */ 696 | 697 | 698 | var INITIAL_CONFIG = new core.InjectionToken("Server.INITIAL_CONFIG"); 699 | /** 700 | * A function that will be executed when calling `renderModuleFactory` or `renderModule` just 701 | * before current platform state is rendered to string. 702 | * 703 | * @publicApi 704 | */ 705 | 706 | var BEFORE_APP_SERIALIZED = new core.InjectionToken("Server.RENDER_MODULE_HOOK"); 707 | var xhr2 = _xhr; // @see https://www.w3.org/Protocols/HTTP/1.1/draft-ietf-http-v11-spec-01#URI-syntax 708 | 709 | var isAbsoluteUrl = /^[a-zA-Z\-\+.]+:\/\//; 710 | 711 | var ServerXhr = 712 | /** @class */ 713 | function () { 714 | function ServerXhr() {} 715 | 716 | ServerXhr.prototype.build = function () { 717 | return new xhr2.XMLHttpRequest(); 718 | }; 719 | 720 | return ServerXhr; 721 | }(); 722 | 723 | ServerXhr.decorators = [{ 724 | type: core.Injectable 725 | }]; 726 | 727 | var ZoneMacroTaskWrapper = 728 | /** @class */ 729 | function () { 730 | function ZoneMacroTaskWrapper() {} 731 | 732 | ZoneMacroTaskWrapper.prototype.wrap = function (request) { 733 | var _this = this || _global; 734 | 735 | return new rxjs.Observable(function (observer) { 736 | var task = null; 737 | var scheduled = false; 738 | var sub = null; 739 | var savedResult = null; 740 | var savedError = null; 741 | 742 | var scheduleTask = function (_task) { 743 | task = _task; 744 | scheduled = true; 745 | 746 | var delegate = _this.delegate(request); 747 | 748 | sub = delegate.subscribe(function (res) { 749 | return savedResult = res; 750 | }, function (err) { 751 | if (!scheduled) { 752 | throw new Error("An http observable was completed twice. This shouldn't happen, please file a bug."); 753 | } 754 | 755 | savedError = err; 756 | scheduled = false; 757 | task.invoke(); 758 | }, function () { 759 | if (!scheduled) { 760 | throw new Error("An http observable was completed twice. This shouldn't happen, please file a bug."); 761 | } 762 | 763 | scheduled = false; 764 | task.invoke(); 765 | }); 766 | }; 767 | 768 | var cancelTask = function (_task) { 769 | if (!scheduled) { 770 | return; 771 | } 772 | 773 | scheduled = false; 774 | 775 | if (sub) { 776 | sub.unsubscribe(); 777 | sub = null; 778 | } 779 | }; 780 | 781 | var onComplete = function () { 782 | if (savedError !== null) { 783 | observer.error(savedError); 784 | } else { 785 | observer.next(savedResult); 786 | observer.complete(); 787 | } 788 | }; // MockBackend for Http is synchronous, which means that if scheduleTask is by 789 | // scheduleMacroTask, the request will hit MockBackend and the response will be 790 | // sent, causing task.invoke() to be called. 791 | 792 | 793 | var _task = Zone.current.scheduleMacroTask("ZoneMacroTaskWrapper.subscribe", onComplete, {}, function () { 794 | return null; 795 | }, cancelTask); 796 | 797 | scheduleTask(_task); 798 | return function () { 799 | if (scheduled && task) { 800 | task.zone.cancelTask(task); 801 | scheduled = false; 802 | } 803 | 804 | if (sub) { 805 | sub.unsubscribe(); 806 | sub = null; 807 | } 808 | }; 809 | }); 810 | }; 811 | 812 | return ZoneMacroTaskWrapper; 813 | }(); 814 | 815 | var ZoneClientBackend = 816 | /** @class */ 817 | function (_super) { 818 | __extends(ZoneClientBackend, _super); 819 | 820 | function ZoneClientBackend(backend, platformLocation, config) { 821 | var _this = _super.call(this || _global) || this || _global; 822 | 823 | _this.backend = backend; 824 | _this.platformLocation = platformLocation; 825 | _this.config = config; 826 | return _this; 827 | } 828 | 829 | ZoneClientBackend.prototype.handle = function (request) { 830 | var _a = (this || _global).platformLocation, 831 | href = _a.href, 832 | protocol = _a.protocol, 833 | hostname = _a.hostname, 834 | port = _a.port; 835 | 836 | if ((this || _global).config.useAbsoluteUrl && !isAbsoluteUrl.test(request.url) && isAbsoluteUrl.test(href)) { 837 | var baseHref = (this || _global).platformLocation.getBaseHrefFromDOM() || href; 838 | var urlPrefix = protocol + "//" + hostname + (port ? ":" + port : ""); 839 | var baseUrl = new URL(baseHref, urlPrefix); 840 | var url = new URL(request.url, baseUrl); 841 | return this.wrap(request.clone({ 842 | url: url.toString() 843 | })); 844 | } 845 | 846 | return this.wrap(request); 847 | }; 848 | 849 | ZoneClientBackend.prototype.delegate = function (request) { 850 | return (this || _global).backend.handle(request); 851 | }; 852 | 853 | return ZoneClientBackend; 854 | }(ZoneMacroTaskWrapper); 855 | 856 | function zoneWrappedInterceptingHandler(backend, injector, platformLocation, config) { 857 | var realBackend = new http.ɵHttpInterceptingHandler(backend, injector); 858 | return new ZoneClientBackend(realBackend, platformLocation, config); 859 | } 860 | 861 | var SERVER_HTTP_PROVIDERS = [{ 862 | provide: common.XhrFactory, 863 | useClass: ServerXhr 864 | }, { 865 | provide: http.HttpHandler, 866 | useFactory: zoneWrappedInterceptingHandler, 867 | deps: [http.HttpBackend, core.Injector, common.PlatformLocation, INITIAL_CONFIG] 868 | }]; 869 | /** 870 | * @license 871 | * Copyright Google LLC All Rights Reserved. 872 | * 873 | * Use of this source code is governed by an MIT-style license that can be 874 | * found in the LICENSE file at https://angular.io/license 875 | */ 876 | 877 | function parseUrl(urlStr) { 878 | var parsedUrl = url.parse(urlStr); 879 | return { 880 | hostname: parsedUrl.hostname || "", 881 | protocol: parsedUrl.protocol || "", 882 | port: parsedUrl.port || "", 883 | pathname: parsedUrl.pathname || "", 884 | search: parsedUrl.search || "", 885 | hash: parsedUrl.hash || "" 886 | }; 887 | } 888 | /** 889 | * Server-side implementation of URL state. Implements `pathname`, `search`, and `hash` 890 | * but not the state stack. 891 | */ 892 | 893 | 894 | var ServerPlatformLocation = 895 | /** @class */ 896 | function () { 897 | function ServerPlatformLocation(_doc, _config) { 898 | (this || _global)._doc = _doc; 899 | (this || _global).href = "/"; 900 | (this || _global).hostname = "/"; 901 | (this || _global).protocol = "/"; 902 | (this || _global).port = "/"; 903 | (this || _global).pathname = "/"; 904 | (this || _global).search = ""; 905 | (this || _global).hash = ""; 906 | (this || _global)._hashUpdate = new rxjs.Subject(); 907 | var config = _config; 908 | 909 | if (!config) { 910 | return; 911 | } 912 | 913 | if (config.url) { 914 | var url_1 = parseUrl(config.url); 915 | (this || _global).protocol = url_1.protocol; 916 | (this || _global).hostname = url_1.hostname; 917 | (this || _global).port = url_1.port; 918 | (this || _global).pathname = url_1.pathname; 919 | (this || _global).search = url_1.search; 920 | (this || _global).hash = url_1.hash; 921 | (this || _global).href = _doc.location.href; 922 | } 923 | 924 | if (config.useAbsoluteUrl) { 925 | if (!config.baseUrl) { 926 | throw new Error("\"PlatformConfig.baseUrl\" must be set if \"useAbsoluteUrl\" is true"); 927 | } 928 | 929 | var url_2 = parseUrl(config.baseUrl); 930 | (this || _global).protocol = url_2.protocol; 931 | (this || _global).hostname = url_2.hostname; 932 | (this || _global).port = url_2.port; 933 | } 934 | } 935 | 936 | ServerPlatformLocation.prototype.getBaseHrefFromDOM = function () { 937 | return common.ɵgetDOM().getBaseHref((this || _global)._doc); 938 | }; 939 | 940 | ServerPlatformLocation.prototype.onPopState = function (fn) { 941 | // No-op: a state stack is not implemented, so 942 | // no events will ever come. 943 | return function () {}; 944 | }; 945 | 946 | ServerPlatformLocation.prototype.onHashChange = function (fn) { 947 | var subscription = (this || _global)._hashUpdate.subscribe(fn); 948 | 949 | return function () { 950 | return subscription.unsubscribe(); 951 | }; 952 | }; 953 | 954 | Object.defineProperty(ServerPlatformLocation.prototype, "url", { 955 | get: function () { 956 | return "" + (this || _global).pathname + (this || _global).search + (this || _global).hash; 957 | }, 958 | enumerable: false, 959 | configurable: true 960 | }); 961 | 962 | ServerPlatformLocation.prototype.setHash = function (value, oldUrl) { 963 | var _this = this || _global; 964 | 965 | if ((this || _global).hash === value) { 966 | // Don't fire events if the hash has not changed. 967 | return; 968 | } 969 | 970 | (this || _global).hash = value; 971 | var newUrl = (this || _global).url; 972 | scheduleMicroTask(function () { 973 | return _this._hashUpdate.next({ 974 | type: "hashchange", 975 | state: null, 976 | oldUrl: oldUrl, 977 | newUrl: newUrl 978 | }); 979 | }); 980 | }; 981 | 982 | ServerPlatformLocation.prototype.replaceState = function (state, title, newUrl) { 983 | var oldUrl = (this || _global).url; 984 | var parsedUrl = parseUrl(newUrl); 985 | (this || _global).pathname = parsedUrl.pathname; 986 | (this || _global).search = parsedUrl.search; 987 | this.setHash(parsedUrl.hash, oldUrl); 988 | }; 989 | 990 | ServerPlatformLocation.prototype.pushState = function (state, title, newUrl) { 991 | this.replaceState(state, title, newUrl); 992 | }; 993 | 994 | ServerPlatformLocation.prototype.forward = function () { 995 | throw new Error("Not implemented"); 996 | }; 997 | 998 | ServerPlatformLocation.prototype.back = function () { 999 | throw new Error("Not implemented"); 1000 | }; // History API isn't available on server, therefore return undefined 1001 | 1002 | 1003 | ServerPlatformLocation.prototype.getState = function () { 1004 | return undefined; 1005 | }; 1006 | 1007 | return ServerPlatformLocation; 1008 | }(); 1009 | 1010 | ServerPlatformLocation.decorators = [{ 1011 | type: core.Injectable 1012 | }]; 1013 | 1014 | ServerPlatformLocation.ctorParameters = function () { 1015 | return [{ 1016 | type: undefined, 1017 | decorators: [{ 1018 | type: core.Inject, 1019 | args: [common.DOCUMENT] 1020 | }] 1021 | }, { 1022 | type: undefined, 1023 | decorators: [{ 1024 | type: core.Optional 1025 | }, { 1026 | type: core.Inject, 1027 | args: [INITIAL_CONFIG] 1028 | }] 1029 | }]; 1030 | }; 1031 | 1032 | function scheduleMicroTask(fn) { 1033 | Zone.current.scheduleMicroTask("scheduleMicrotask", fn); 1034 | } 1035 | /** 1036 | * @license 1037 | * Copyright Google LLC All Rights Reserved. 1038 | * 1039 | * Use of this source code is governed by an MIT-style license that can be 1040 | * found in the LICENSE file at https://angular.io/license 1041 | */ 1042 | 1043 | 1044 | var ServerEventManagerPlugin 1045 | /* extends EventManagerPlugin which is private */ 1046 | = 1047 | /** @class */ 1048 | function () { 1049 | function ServerEventManagerPlugin(doc) { 1050 | (this || _global).doc = doc; 1051 | } // Handle all events on the server. 1052 | 1053 | 1054 | ServerEventManagerPlugin.prototype.supports = function (eventName) { 1055 | return true; 1056 | }; 1057 | 1058 | ServerEventManagerPlugin.prototype.addEventListener = function (element, eventName, handler) { 1059 | return common.ɵgetDOM().onAndCancel(element, eventName, handler); 1060 | }; 1061 | /** @deprecated No longer being used in Ivy code. To be removed in version 14. */ 1062 | 1063 | 1064 | ServerEventManagerPlugin.prototype.addGlobalEventListener = function (element, eventName, handler) { 1065 | var target = common.ɵgetDOM().getGlobalEventTarget((this || _global).doc, element); 1066 | 1067 | if (!target) { 1068 | throw new Error("Unsupported event target " + target + " for event " + eventName); 1069 | } 1070 | 1071 | return this.addEventListener(target, eventName, handler); 1072 | }; 1073 | 1074 | return ServerEventManagerPlugin; 1075 | }(); 1076 | 1077 | ServerEventManagerPlugin.decorators = [{ 1078 | type: core.Injectable 1079 | }]; 1080 | 1081 | ServerEventManagerPlugin.ctorParameters = function () { 1082 | return [{ 1083 | type: undefined, 1084 | decorators: [{ 1085 | type: core.Inject, 1086 | args: [common.DOCUMENT] 1087 | }] 1088 | }]; 1089 | }; 1090 | 1091 | var EMPTY_ARRAY = []; 1092 | var DEFAULT_SCHEMA = new compiler.DomElementSchemaRegistry(); 1093 | 1094 | var ServerRendererFactory2 = 1095 | /** @class */ 1096 | function () { 1097 | function ServerRendererFactory2(eventManager, ngZone, document, sharedStylesHost) { 1098 | (this || _global).eventManager = eventManager; 1099 | (this || _global).ngZone = ngZone; 1100 | (this || _global).document = document; 1101 | (this || _global).sharedStylesHost = sharedStylesHost; 1102 | (this || _global).rendererByCompId = new Map(); 1103 | (this || _global).schema = DEFAULT_SCHEMA; 1104 | (this || _global).defaultRenderer = new DefaultServerRenderer2(eventManager, document, ngZone, (this || _global).schema); 1105 | } 1106 | 1107 | ServerRendererFactory2.prototype.createRenderer = function (element, type) { 1108 | if (!element || !type) { 1109 | return (this || _global).defaultRenderer; 1110 | } 1111 | 1112 | switch (type.encapsulation) { 1113 | case core.ViewEncapsulation.Emulated: 1114 | { 1115 | var renderer = (this || _global).rendererByCompId.get(type.id); 1116 | 1117 | if (!renderer) { 1118 | renderer = new EmulatedEncapsulationServerRenderer2((this || _global).eventManager, (this || _global).document, (this || _global).ngZone, (this || _global).sharedStylesHost, (this || _global).schema, type); 1119 | 1120 | (this || _global).rendererByCompId.set(type.id, renderer); 1121 | } 1122 | 1123 | renderer.applyToHost(element); 1124 | return renderer; 1125 | } 1126 | 1127 | default: 1128 | { 1129 | if (!(this || _global).rendererByCompId.has(type.id)) { 1130 | var styles = platformBrowser.ɵflattenStyles(type.id, type.styles, []); 1131 | 1132 | (this || _global).sharedStylesHost.addStyles(styles); 1133 | 1134 | (this || _global).rendererByCompId.set(type.id, (this || _global).defaultRenderer); 1135 | } 1136 | 1137 | return (this || _global).defaultRenderer; 1138 | } 1139 | } 1140 | }; 1141 | 1142 | ServerRendererFactory2.prototype.begin = function () {}; 1143 | 1144 | ServerRendererFactory2.prototype.end = function () {}; 1145 | 1146 | return ServerRendererFactory2; 1147 | }(); 1148 | 1149 | ServerRendererFactory2.decorators = [{ 1150 | type: core.Injectable 1151 | }]; 1152 | 1153 | ServerRendererFactory2.ctorParameters = function () { 1154 | return [{ 1155 | type: platformBrowser.EventManager 1156 | }, { 1157 | type: core.NgZone 1158 | }, { 1159 | type: undefined, 1160 | decorators: [{ 1161 | type: core.Inject, 1162 | args: [common.DOCUMENT] 1163 | }] 1164 | }, { 1165 | type: platformBrowser.ɵSharedStylesHost 1166 | }]; 1167 | }; 1168 | 1169 | var DefaultServerRenderer2 = 1170 | /** @class */ 1171 | function () { 1172 | function DefaultServerRenderer2(eventManager, document, ngZone, schema) { 1173 | (this || _global).eventManager = eventManager; 1174 | (this || _global).document = document; 1175 | (this || _global).ngZone = ngZone; 1176 | (this || _global).schema = schema; 1177 | (this || _global).data = Object.create(null); 1178 | } 1179 | 1180 | DefaultServerRenderer2.prototype.destroy = function () {}; 1181 | 1182 | DefaultServerRenderer2.prototype.createElement = function (name, namespace, debugInfo) { 1183 | if (namespace) { 1184 | var doc = (this || _global).document || common.ɵgetDOM().getDefaultDocument(); // TODO(FW-811): Ivy may cause issues here because it's passing around 1185 | // full URIs for namespaces, therefore this lookup will fail. 1186 | 1187 | return doc.createElementNS(platformBrowser.ɵNAMESPACE_URIS[namespace], name); 1188 | } 1189 | 1190 | return common.ɵgetDOM().createElement(name, (this || _global).document); 1191 | }; 1192 | 1193 | DefaultServerRenderer2.prototype.createComment = function (value, debugInfo) { 1194 | return common.ɵgetDOM().getDefaultDocument().createComment(value); 1195 | }; 1196 | 1197 | DefaultServerRenderer2.prototype.createText = function (value, debugInfo) { 1198 | var doc = common.ɵgetDOM().getDefaultDocument(); 1199 | return doc.createTextNode(value); 1200 | }; 1201 | 1202 | DefaultServerRenderer2.prototype.appendChild = function (parent, newChild) { 1203 | parent.appendChild(newChild); 1204 | }; 1205 | 1206 | DefaultServerRenderer2.prototype.insertBefore = function (parent, newChild, refChild) { 1207 | if (parent) { 1208 | parent.insertBefore(newChild, refChild); 1209 | } 1210 | }; 1211 | 1212 | DefaultServerRenderer2.prototype.removeChild = function (parent, oldChild) { 1213 | if (parent) { 1214 | parent.removeChild(oldChild); 1215 | } 1216 | }; 1217 | 1218 | DefaultServerRenderer2.prototype.selectRootElement = function (selectorOrNode, debugInfo) { 1219 | var el; 1220 | 1221 | if (typeof selectorOrNode === "string") { 1222 | el = (this || _global).document.querySelector(selectorOrNode); 1223 | 1224 | if (!el) { 1225 | throw new Error("The selector \"" + selectorOrNode + "\" did not match any elements"); 1226 | } 1227 | } else { 1228 | el = selectorOrNode; 1229 | } 1230 | 1231 | while (el.firstChild) { 1232 | el.removeChild(el.firstChild); 1233 | } 1234 | 1235 | return el; 1236 | }; 1237 | 1238 | DefaultServerRenderer2.prototype.parentNode = function (node) { 1239 | return node.parentNode; 1240 | }; 1241 | 1242 | DefaultServerRenderer2.prototype.nextSibling = function (node) { 1243 | return node.nextSibling; 1244 | }; 1245 | 1246 | DefaultServerRenderer2.prototype.setAttribute = function (el, name, value, namespace) { 1247 | if (namespace) { 1248 | // TODO(FW-811): Ivy may cause issues here because it's passing around 1249 | // full URIs for namespaces, therefore this lookup will fail. 1250 | el.setAttributeNS(platformBrowser.ɵNAMESPACE_URIS[namespace], namespace + ":" + name, value); 1251 | } else { 1252 | el.setAttribute(name, value); 1253 | } 1254 | }; 1255 | 1256 | DefaultServerRenderer2.prototype.removeAttribute = function (el, name, namespace) { 1257 | if (namespace) { 1258 | // TODO(FW-811): Ivy may cause issues here because it's passing around 1259 | // full URIs for namespaces, therefore this lookup will fail. 1260 | el.removeAttributeNS(platformBrowser.ɵNAMESPACE_URIS[namespace], name); 1261 | } else { 1262 | el.removeAttribute(name); 1263 | } 1264 | }; 1265 | 1266 | DefaultServerRenderer2.prototype.addClass = function (el, name) { 1267 | el.classList.add(name); 1268 | }; 1269 | 1270 | DefaultServerRenderer2.prototype.removeClass = function (el, name) { 1271 | el.classList.remove(name); 1272 | }; 1273 | 1274 | DefaultServerRenderer2.prototype.setStyle = function (el, style, value, flags) { 1275 | style = style.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(); 1276 | 1277 | var styleMap = _readStyleAttribute(el); 1278 | 1279 | if (flags & core.RendererStyleFlags2.Important) { 1280 | value += " !important"; 1281 | } 1282 | 1283 | styleMap[style] = value == null ? "" : value; 1284 | 1285 | _writeStyleAttribute(el, styleMap); 1286 | }; 1287 | 1288 | DefaultServerRenderer2.prototype.removeStyle = function (el, style, flags) { 1289 | // IE requires '' instead of null 1290 | // see https://github.com/angular/angular/issues/7916 1291 | this.setStyle(el, style, "", flags); 1292 | }; // The value was validated already as a property binding, against the property name. 1293 | // To know this value is safe to use as an attribute, the security context of the 1294 | // attribute with the given name is checked against that security context of the 1295 | // property. 1296 | 1297 | 1298 | DefaultServerRenderer2.prototype._isSafeToReflectProperty = function (tagName, propertyName) { 1299 | return (this || _global).schema.securityContext(tagName, propertyName, true) === (this || _global).schema.securityContext(tagName, propertyName, false); 1300 | }; 1301 | 1302 | DefaultServerRenderer2.prototype.setProperty = function (el, name, value) { 1303 | checkNoSyntheticProp(name, "property"); 1304 | 1305 | if (name === "innerText") { 1306 | // Domino does not support innerText. Just map it to textContent. 1307 | el.textContent = value; 1308 | } 1309 | 1310 | el[name] = value; // Mirror property values for known HTML element properties in the attributes. 1311 | // Skip `innerhtml` which is conservatively marked as an attribute for security 1312 | // purposes but is not actually an attribute. 1313 | 1314 | var tagName = el.tagName.toLowerCase(); 1315 | 1316 | if (value != null && (typeof value === "number" || typeof value == "string") && name.toLowerCase() !== "innerhtml" && (this || _global).schema.hasElement(tagName, EMPTY_ARRAY) && (this || _global).schema.hasProperty(tagName, name, EMPTY_ARRAY) && this._isSafeToReflectProperty(tagName, name)) { 1317 | this.setAttribute(el, name, value.toString()); 1318 | } 1319 | }; 1320 | 1321 | DefaultServerRenderer2.prototype.setValue = function (node, value) { 1322 | node.textContent = value; 1323 | }; 1324 | 1325 | DefaultServerRenderer2.prototype.listen = function (target, eventName, callback) { 1326 | checkNoSyntheticProp(eventName, "listener"); 1327 | 1328 | if (typeof target === "string") { 1329 | return (this || _global).eventManager.addGlobalEventListener(target, eventName, this.decoratePreventDefault(callback)); 1330 | } 1331 | 1332 | return (this || _global).eventManager.addEventListener(target, eventName, this.decoratePreventDefault(callback)); 1333 | }; 1334 | 1335 | DefaultServerRenderer2.prototype.decoratePreventDefault = function (eventHandler) { 1336 | var _this = this || _global; 1337 | 1338 | return function (event) { 1339 | // Ivy uses `Function` as a special token that allows us to unwrap the function 1340 | // so that it can be invoked programmatically by `DebugNode.triggerEventHandler`. 1341 | if (event === Function) { 1342 | return eventHandler; 1343 | } // Run the event handler inside the ngZone because event handlers are not patched 1344 | // by Zone on the server. This is required only for tests. 1345 | 1346 | 1347 | var allowDefaultBehavior = _this.ngZone.runGuarded(function () { 1348 | return eventHandler(event); 1349 | }); 1350 | 1351 | if (allowDefaultBehavior === false) { 1352 | event.preventDefault(); 1353 | event.returnValue = false; 1354 | } 1355 | 1356 | return undefined; 1357 | }; 1358 | }; 1359 | 1360 | return DefaultServerRenderer2; 1361 | }(); 1362 | 1363 | var AT_CHARCODE = "@".charCodeAt(0); 1364 | 1365 | function checkNoSyntheticProp(name, nameKind) { 1366 | if (name.charCodeAt(0) === AT_CHARCODE) { 1367 | throw new Error("Found the synthetic " + nameKind + " " + name + ". Please include either \"BrowserAnimationsModule\" or \"NoopAnimationsModule\" in your application."); 1368 | } 1369 | } 1370 | 1371 | var EmulatedEncapsulationServerRenderer2 = 1372 | /** @class */ 1373 | function (_super) { 1374 | __extends(EmulatedEncapsulationServerRenderer2, _super); 1375 | 1376 | function EmulatedEncapsulationServerRenderer2(eventManager, document, ngZone, sharedStylesHost, schema, component) { 1377 | var _this = _super.call(this || _global, eventManager, document, ngZone, schema) || this || _global; 1378 | 1379 | _this.component = component; // Add a 's' prefix to style attributes to indicate server. 1380 | 1381 | var componentId = "s" + component.id; 1382 | var styles = platformBrowser.ɵflattenStyles(componentId, component.styles, []); 1383 | sharedStylesHost.addStyles(styles); 1384 | _this.contentAttr = platformBrowser.ɵshimContentAttribute(componentId); 1385 | _this.hostAttr = platformBrowser.ɵshimHostAttribute(componentId); 1386 | return _this; 1387 | } 1388 | 1389 | EmulatedEncapsulationServerRenderer2.prototype.applyToHost = function (element) { 1390 | _super.prototype.setAttribute.call(this || _global, element, (this || _global).hostAttr, ""); 1391 | }; 1392 | 1393 | EmulatedEncapsulationServerRenderer2.prototype.createElement = function (parent, name) { 1394 | var el = _super.prototype.createElement.call(this || _global, parent, name, (this || _global).document); 1395 | 1396 | _super.prototype.setAttribute.call(this || _global, el, (this || _global).contentAttr, ""); 1397 | 1398 | return el; 1399 | }; 1400 | 1401 | return EmulatedEncapsulationServerRenderer2; 1402 | }(DefaultServerRenderer2); 1403 | 1404 | function _readStyleAttribute(element) { 1405 | var styleMap = {}; 1406 | var styleAttribute = element.getAttribute("style"); 1407 | 1408 | if (styleAttribute) { 1409 | var styleList = styleAttribute.split(/;+/g); 1410 | 1411 | for (var i = 0; i < styleList.length; i++) { 1412 | var style = styleList[i].trim(); 1413 | 1414 | if (style.length > 0) { 1415 | var colonIndex = style.indexOf(":"); 1416 | 1417 | if (colonIndex === -1) { 1418 | throw new Error("Invalid CSS style: " + style); 1419 | } 1420 | 1421 | var name = style.substr(0, colonIndex).trim(); 1422 | styleMap[name] = style.substr(colonIndex + 1).trim(); 1423 | } 1424 | } 1425 | } 1426 | 1427 | return styleMap; 1428 | } 1429 | 1430 | function _writeStyleAttribute(element, styleMap) { 1431 | var styleAttrValue = ""; 1432 | 1433 | for (var key in styleMap) { 1434 | var newValue = styleMap[key]; 1435 | 1436 | if (newValue != null) { 1437 | styleAttrValue += key + ":" + styleMap[key] + ";"; 1438 | } 1439 | } 1440 | 1441 | element.setAttribute("style", styleAttrValue); 1442 | } 1443 | 1444 | var ServerStylesHost = 1445 | /** @class */ 1446 | function (_super) { 1447 | __extends(ServerStylesHost, _super); 1448 | 1449 | function ServerStylesHost(doc, transitionId) { 1450 | var _this = _super.call(this || _global) || this || _global; 1451 | 1452 | _this.doc = doc; 1453 | _this.transitionId = transitionId; 1454 | _this.head = null; 1455 | _this._styleNodes = new Set(); 1456 | _this.head = doc.getElementsByTagName("head")[0]; 1457 | return _this; 1458 | } 1459 | 1460 | ServerStylesHost.prototype._addStyle = function (style) { 1461 | var adapter = common.ɵgetDOM(); 1462 | var el = adapter.createElement("style"); 1463 | el.textContent = style; 1464 | 1465 | if (!!(this || _global).transitionId) { 1466 | el.setAttribute("ng-transition", (this || _global).transitionId); 1467 | } 1468 | 1469 | (this || _global).head.appendChild(el); 1470 | 1471 | (this || _global)._styleNodes.add(el); 1472 | }; 1473 | 1474 | ServerStylesHost.prototype.onStylesAdded = function (additions) { 1475 | var _this = this || _global; 1476 | 1477 | additions.forEach(function (style) { 1478 | return _this._addStyle(style); 1479 | }); 1480 | }; 1481 | 1482 | ServerStylesHost.prototype.ngOnDestroy = function () { 1483 | (this || _global)._styleNodes.forEach(function (styleNode) { 1484 | return styleNode.remove(); 1485 | }); 1486 | }; 1487 | 1488 | return ServerStylesHost; 1489 | }(platformBrowser.ɵSharedStylesHost); 1490 | 1491 | ServerStylesHost.decorators = [{ 1492 | type: core.Injectable 1493 | }]; 1494 | 1495 | ServerStylesHost.ctorParameters = function () { 1496 | return [{ 1497 | type: undefined, 1498 | decorators: [{ 1499 | type: core.Inject, 1500 | args: [common.DOCUMENT] 1501 | }] 1502 | }, { 1503 | type: String, 1504 | decorators: [{ 1505 | type: core.Optional 1506 | }, { 1507 | type: core.Inject, 1508 | args: [platformBrowser.ɵTRANSITION_ID] 1509 | }] 1510 | }]; 1511 | }; 1512 | /** 1513 | * @license 1514 | * Copyright Google LLC All Rights Reserved. 1515 | * 1516 | * Use of this source code is governed by an MIT-style license that can be 1517 | * found in the LICENSE file at https://angular.io/license 1518 | */ 1519 | 1520 | 1521 | function notSupported(feature) { 1522 | throw new Error("platform-server does not support '" + feature + "'."); 1523 | } 1524 | 1525 | var INTERNAL_SERVER_PLATFORM_PROVIDERS = [{ 1526 | provide: common.DOCUMENT, 1527 | useFactory: _document, 1528 | deps: [core.Injector] 1529 | }, { 1530 | provide: core.PLATFORM_ID, 1531 | useValue: common.ɵPLATFORM_SERVER_ID 1532 | }, { 1533 | provide: core.PLATFORM_INITIALIZER, 1534 | useFactory: initDominoAdapter, 1535 | multi: true, 1536 | deps: [core.Injector] 1537 | }, { 1538 | provide: common.PlatformLocation, 1539 | useClass: ServerPlatformLocation, 1540 | deps: [common.DOCUMENT, [core.Optional, INITIAL_CONFIG]] 1541 | }, { 1542 | provide: PlatformState, 1543 | deps: [common.DOCUMENT] 1544 | }, // Add special provider that allows multiple instances of platformServer* to be created. 1545 | { 1546 | provide: core.ɵALLOW_MULTIPLE_PLATFORMS, 1547 | useValue: true 1548 | }]; 1549 | 1550 | function initDominoAdapter(injector) { 1551 | return function () { 1552 | DominoAdapter.makeCurrent(); 1553 | }; 1554 | } 1555 | 1556 | function instantiateServerRendererFactory(renderer, engine, zone) { 1557 | return new animations.ɵAnimationRendererFactory(renderer, engine, zone); 1558 | } 1559 | 1560 | var SERVER_RENDER_PROVIDERS = [ServerRendererFactory2, { 1561 | provide: core.RendererFactory2, 1562 | useFactory: instantiateServerRendererFactory, 1563 | deps: [ServerRendererFactory2, browser.ɵAnimationEngine, core.NgZone] 1564 | }, ServerStylesHost, { 1565 | provide: platformBrowser.ɵSharedStylesHost, 1566 | useExisting: ServerStylesHost 1567 | }, { 1568 | provide: platformBrowser.EVENT_MANAGER_PLUGINS, 1569 | multi: true, 1570 | useClass: ServerEventManagerPlugin 1571 | }]; 1572 | /** 1573 | * The ng module for the server. 1574 | * 1575 | * @publicApi 1576 | */ 1577 | 1578 | var ServerModule = 1579 | /** @class */ 1580 | function () { 1581 | function ServerModule() {} 1582 | 1583 | return ServerModule; 1584 | }(); 1585 | 1586 | ServerModule.decorators = [{ 1587 | type: core.NgModule, 1588 | args: [{ 1589 | exports: [platformBrowser.BrowserModule], 1590 | imports: [http.HttpClientModule, animations.NoopAnimationsModule], 1591 | providers: [SERVER_RENDER_PROVIDERS, SERVER_HTTP_PROVIDERS, { 1592 | provide: core.Testability, 1593 | useValue: null 1594 | }, { 1595 | provide: common.ViewportScroller, 1596 | useClass: common.ɵNullViewportScroller 1597 | }] 1598 | }] 1599 | }]; 1600 | 1601 | function _document(injector) { 1602 | var config = injector.get(INITIAL_CONFIG, null); 1603 | var document = config && config.document ? parseDocument(config.document, config.url) : common.ɵgetDOM().createHtmlDocument(); // Tell ivy about the global document 1604 | 1605 | core.ɵsetDocument(document); 1606 | return document; 1607 | } 1608 | /** 1609 | * @publicApi 1610 | */ 1611 | 1612 | 1613 | var platformServer = core.createPlatformFactory(core.platformCore, "server", INTERNAL_SERVER_PLATFORM_PROVIDERS); 1614 | /** 1615 | * The server platform that supports the runtime compiler. 1616 | * 1617 | * @publicApi 1618 | */ 1619 | 1620 | var platformDynamicServer = core.createPlatformFactory(platformBrowserDynamic.ɵplatformCoreDynamic, "serverDynamic", INTERNAL_SERVER_PLATFORM_PROVIDERS); 1621 | /** 1622 | * @license 1623 | * Copyright Google LLC All Rights Reserved. 1624 | * 1625 | * Use of this source code is governed by an MIT-style license that can be 1626 | * found in the LICENSE file at https://angular.io/license 1627 | */ 1628 | 1629 | function serializeTransferStateFactory(doc, appId, transferStore) { 1630 | return function () { 1631 | var script = doc.createElement("script"); 1632 | script.id = appId + "-state"; 1633 | script.setAttribute("type", "application/json"); 1634 | script.textContent = platformBrowser.ɵescapeHtml(transferStore.toJson()); 1635 | doc.body.appendChild(script); 1636 | }; 1637 | } 1638 | /** 1639 | * NgModule to install on the server side while using the `TransferState` to transfer state from 1640 | * server to client. 1641 | * 1642 | * @publicApi 1643 | */ 1644 | 1645 | 1646 | var ServerTransferStateModule = 1647 | /** @class */ 1648 | function () { 1649 | function ServerTransferStateModule() {} 1650 | 1651 | return ServerTransferStateModule; 1652 | }(); 1653 | 1654 | ServerTransferStateModule.decorators = [{ 1655 | type: core.NgModule, 1656 | args: [{ 1657 | providers: [platformBrowser.TransferState, { 1658 | provide: BEFORE_APP_SERIALIZED, 1659 | useFactory: serializeTransferStateFactory, 1660 | deps: [common.DOCUMENT, core.APP_ID, platformBrowser.TransferState], 1661 | multi: true 1662 | }] 1663 | }] 1664 | }]; 1665 | 1666 | function _getPlatform(platformFactory, options) { 1667 | var extraProviders = options.extraProviders ? options.extraProviders : []; 1668 | return platformFactory([{ 1669 | provide: INITIAL_CONFIG, 1670 | useValue: { 1671 | document: options.document, 1672 | url: options.url 1673 | } 1674 | }, extraProviders]); 1675 | } 1676 | 1677 | function _render(platform, moduleRefPromise) { 1678 | return moduleRefPromise.then(function (moduleRef) { 1679 | // var transitionId = moduleRef.injector.get(platformBrowser.ɵTRANSITION_ID, null); 1680 | // 1681 | // if (!transitionId) { 1682 | // throw new Error("renderModule[Factory]() requires the use of BrowserModule.withServerTransition() to ensure\nthe server-rendered app can be properly bootstrapped into a client app."); 1683 | // } 1684 | 1685 | var applicationRef = moduleRef.injector.get(core.ApplicationRef); 1686 | return applicationRef.isStable.pipe(operators.first(function (isStable) { 1687 | return isStable; 1688 | })).toPromise().then(function () { 1689 | var e_1, _a; 1690 | 1691 | var platformState = platform.injector.get(PlatformState); 1692 | var asyncPromises = []; // Run any BEFORE_APP_SERIALIZED callbacks just before rendering to string. 1693 | 1694 | var callbacks = moduleRef.injector.get(BEFORE_APP_SERIALIZED, null); 1695 | 1696 | if (callbacks) { 1697 | try { 1698 | for (var callbacks_1 = __values(callbacks), callbacks_1_1 = callbacks_1.next(); !callbacks_1_1.done; callbacks_1_1 = callbacks_1.next()) { 1699 | var callback = callbacks_1_1.value; 1700 | 1701 | try { 1702 | var callbackResult = callback(); 1703 | 1704 | if (core.ɵisPromise(callbackResult)) { 1705 | // TODO: in TS3.7, callbackResult is void. 1706 | asyncPromises.push(callbackResult); 1707 | } 1708 | } catch (e) { 1709 | // Ignore exceptions. 1710 | console.warn("Ignoring BEFORE_APP_SERIALIZED Exception: ", e); 1711 | } 1712 | } 1713 | } catch (e_1_1) { 1714 | e_1 = { 1715 | error: e_1_1 1716 | }; 1717 | } finally { 1718 | try { 1719 | if (callbacks_1_1 && !callbacks_1_1.done && (_a = callbacks_1.return)) _a.call(callbacks_1); 1720 | } finally { 1721 | if (e_1) throw e_1.error; 1722 | } 1723 | } 1724 | } 1725 | 1726 | var complete = function () { 1727 | var output = platformState.renderToString(); 1728 | platform.destroy(); 1729 | return output; 1730 | }; 1731 | 1732 | if (asyncPromises.length === 0) { 1733 | return complete(); 1734 | } 1735 | 1736 | return Promise.all(asyncPromises.map(function (asyncPromise) { 1737 | return asyncPromise.catch(function (e) { 1738 | console.warn("Ignoring BEFORE_APP_SERIALIZED Exception: ", e); 1739 | }); 1740 | })).then(complete); 1741 | }); 1742 | }); 1743 | } 1744 | /** 1745 | * Renders a Module to string. 1746 | * 1747 | * `document` is the full document HTML of the page to render, as a string. 1748 | * `url` is the URL for the current render request. 1749 | * `extraProviders` are the platform level providers for the current render request. 1750 | * 1751 | * If compiling with the ViewEngine renderer, do not use this in a production server environment. 1752 | * Use pre-compiled {@link NgModuleFactory} with {@link renderModuleFactory} instead. If 1753 | * compiling with the Ivy renderer, this method is the recommended rendering method for 1754 | * platform-server. 1755 | * 1756 | * @publicApi 1757 | */ 1758 | 1759 | 1760 | function renderModule(module, options) { 1761 | var platform = _getPlatform(platformDynamicServer, options); 1762 | 1763 | return _render(platform, platform.bootstrapModule(module)); 1764 | } 1765 | /** 1766 | * Renders a {@link NgModuleFactory} to string. 1767 | * 1768 | * `document` is the full document HTML of the page to render, as a string. 1769 | * `url` is the URL for the current render request. 1770 | * `extraProviders` are the platform level providers for the current render request. 1771 | * 1772 | * @publicApi 1773 | */ 1774 | 1775 | 1776 | function renderModuleFactory(moduleFactory, options) { 1777 | var platform = _getPlatform(platformServer, options); 1778 | 1779 | return _render(platform, platform.bootstrapModuleFactory(moduleFactory)); 1780 | } 1781 | /** 1782 | * @license 1783 | * Copyright Google LLC All Rights Reserved. 1784 | * 1785 | * Use of this source code is governed by an MIT-style license that can be 1786 | * found in the LICENSE file at https://angular.io/license 1787 | */ 1788 | 1789 | /** 1790 | * @license 1791 | * Copyright Google LLC All Rights Reserved. 1792 | * 1793 | * Use of this source code is governed by an MIT-style license that can be 1794 | * found in the LICENSE file at https://angular.io/license 1795 | */ 1796 | 1797 | /** 1798 | * @publicApi 1799 | */ 1800 | 1801 | 1802 | var VERSION = new core.Version("12.0.3"); 1803 | /** 1804 | * @license 1805 | * Copyright Google LLC All Rights Reserved. 1806 | * 1807 | * Use of this source code is governed by an MIT-style license that can be 1808 | * found in the LICENSE file at https://angular.io/license 1809 | */ 1810 | 1811 | /** 1812 | * @license 1813 | * Copyright Google LLC All Rights Reserved. 1814 | * 1815 | * Use of this source code is governed by an MIT-style license that can be 1816 | * found in the LICENSE file at https://angular.io/license 1817 | */ 1818 | // This file only reexports content of the `src` folder. Keep it that way. 1819 | 1820 | /** 1821 | * @license 1822 | * Copyright Google LLC All Rights Reserved. 1823 | * 1824 | * Use of this source code is governed by an MIT-style license that can be 1825 | * found in the LICENSE file at https://angular.io/license 1826 | */ 1827 | 1828 | /** 1829 | * Generated bundle index. Do not edit. 1830 | */ 1831 | 1832 | exports.BEFORE_APP_SERIALIZED = BEFORE_APP_SERIALIZED; 1833 | exports.INITIAL_CONFIG = INITIAL_CONFIG; 1834 | exports.PlatformState = PlatformState; 1835 | exports.ServerModule = ServerModule; 1836 | exports.ServerTransferStateModule = ServerTransferStateModule; 1837 | exports.VERSION = VERSION; 1838 | exports.platformDynamicServer = platformDynamicServer; 1839 | exports.platformServer = platformServer; 1840 | exports.renderModule = renderModule; 1841 | exports.renderModuleFactory = renderModuleFactory; 1842 | exports.ɵINTERNAL_SERVER_PLATFORM_PROVIDERS = INTERNAL_SERVER_PLATFORM_PROVIDERS; 1843 | exports.ɵSERVER_RENDER_PROVIDERS = SERVER_RENDER_PROVIDERS; 1844 | exports.ɵServerRendererFactory2 = ServerRendererFactory2; 1845 | exports.ɵangular_packages_platform_server_platform_server_a = instantiateServerRendererFactory; 1846 | exports.ɵangular_packages_platform_server_platform_server_b = serializeTransferStateFactory; 1847 | exports.ɵangular_packages_platform_server_platform_server_c = ServerStylesHost; 1848 | exports.ɵangular_packages_platform_server_platform_server_d = ServerEventManagerPlugin; 1849 | exports.ɵangular_packages_platform_server_platform_server_e = ServerXhr; 1850 | exports.ɵangular_packages_platform_server_platform_server_f = zoneWrappedInterceptingHandler; 1851 | exports.ɵangular_packages_platform_server_platform_server_g = SERVER_HTTP_PROVIDERS; 1852 | Object.defineProperty(exports, "__esModule", { 1853 | value: true 1854 | }); 1855 | }); 1856 | const BEFORE_APP_SERIALIZED = exports.BEFORE_APP_SERIALIZED, 1857 | INITIAL_CONFIG = exports.INITIAL_CONFIG, 1858 | PlatformState = exports.PlatformState, 1859 | ServerModule = exports.ServerModule, 1860 | ServerTransferStateModule = exports.ServerTransferStateModule, 1861 | VERSION = exports.VERSION, 1862 | platformDynamicServer = exports.platformDynamicServer, 1863 | platformServer = exports.platformServer, 1864 | renderModule = exports.renderModule, 1865 | renderModuleFactory = exports.renderModuleFactory, 1866 | ɵINTERNAL_SERVER_PLATFORM_PROVIDERS = exports.ɵINTERNAL_SERVER_PLATFORM_PROVIDERS, 1867 | ɵSERVER_RENDER_PROVIDERS = exports.ɵSERVER_RENDER_PROVIDERS, 1868 | ɵServerRendererFactory2 = exports.ɵServerRendererFactory2, 1869 | ɵangular_packages_platform_server_platform_server_a = exports.ɵangular_packages_platform_server_platform_server_a, 1870 | ɵangular_packages_platform_server_platform_server_b = exports.ɵangular_packages_platform_server_platform_server_b, 1871 | ɵangular_packages_platform_server_platform_server_c = exports.ɵangular_packages_platform_server_platform_server_c, 1872 | ɵangular_packages_platform_server_platform_server_d = exports.ɵangular_packages_platform_server_platform_server_d, 1873 | ɵangular_packages_platform_server_platform_server_e = exports.ɵangular_packages_platform_server_platform_server_e, 1874 | ɵangular_packages_platform_server_platform_server_f = exports.ɵangular_packages_platform_server_platform_server_f, 1875 | ɵangular_packages_platform_server_platform_server_g = exports.ɵangular_packages_platform_server_platform_server_g, 1876 | __esModule = exports.__esModule; 1877 | 1878 | export default exports; 1879 | export { BEFORE_APP_SERIALIZED, INITIAL_CONFIG, PlatformState, ServerModule, ServerTransferStateModule, VERSION, __esModule, platformDynamicServer, platformServer, renderModule, renderModuleFactory, ɵINTERNAL_SERVER_PLATFORM_PROVIDERS, ɵSERVER_RENDER_PROVIDERS, ɵServerRendererFactory2, ɵangular_packages_platform_server_platform_server_a, ɵangular_packages_platform_server_platform_server_b, ɵangular_packages_platform_server_platform_server_c, ɵangular_packages_platform_server_platform_server_d, ɵangular_packages_platform_server_platform_server_e, ɵangular_packages_platform_server_platform_server_f, ɵangular_packages_platform_server_platform_server_g }; 1880 | 1881 | //# sourceMappingURL=platform-server@12.0.3!cjs.map 1882 | -------------------------------------------------------------------------------- /resource-loader.ts: -------------------------------------------------------------------------------- 1 | import { ResourceLoader } from 'https://jspm.dev/@angular/compiler@11'; 2 | import { Injector } from 'https://jspm.dev/@angular/core@11'; 3 | import { join } from "https://deno.land/std@0.89.0/path/posix.ts"; 4 | import { RESOURCE_PATH } from './bootstrap.ts'; 5 | 6 | const { readFile } = Deno; 7 | const decoder = new TextDecoder(); 8 | 9 | export class DenoFileSystemResourceLoader extends ResourceLoader { 10 | private readonly filesCache: Map = new Map() 11 | private readonly resourcePath: string; 12 | 13 | // @ts-ignore 14 | constructor(private readonly injector: Injector) { 15 | super(); 16 | 17 | this.resourcePath = this.injector.get(RESOURCE_PATH); 18 | } 19 | 20 | resolve(url: string, baseUrl: string): string { 21 | // Angular assembles absolute URL's and prefixes them with // 22 | if (url.indexOf('/') !== 0) { 23 | // Resolve relative URL's based on the app root. 24 | return join(baseUrl, url); 25 | } else { 26 | return url; 27 | } 28 | } 29 | 30 | get(url: string, aa?: any): Promise { 31 | const appDir = this.resourcePath || ''; 32 | const filePath = this.resolve(url, appDir); 33 | 34 | if (this.filesCache.has(filePath)) { 35 | return Promise.resolve(this.filesCache.get(filePath) + ''); 36 | } 37 | 38 | return readFile(filePath).then(source => { 39 | const template: string = decoder.decode(source) 40 | this.filesCache.set(filePath, template) 41 | 42 | return template; 43 | }); 44 | } 45 | } 46 | --------------------------------------------------------------------------------