Left: | ||
Right: |
OLD | NEW |
---|---|
1 // Copyright (C) 2008-2011 Google Inc. | 1 // Copyright (C) 2008-2011 Google Inc. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 2101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2112 * Return the object which stores expando properties for a given | 2112 * Return the object which stores expando properties for a given |
2113 * host DOM node. | 2113 * host DOM node. |
2114 */ | 2114 */ |
2115 function getNodeExpandoStorage(node) { | 2115 function getNodeExpandoStorage(node) { |
2116 var s = nodeExpandos.get(node); | 2116 var s = nodeExpandos.get(node); |
2117 if (s === undefined) { | 2117 if (s === undefined) { |
2118 nodeExpandos.set(node, s = {}); | 2118 nodeExpandos.set(node, s = {}); |
2119 } | 2119 } |
2120 return s; | 2120 return s; |
2121 } | 2121 } |
2122 ······ | |
2123 var nodeClassNoImplWarnings = {}; | |
2122 | 2124 |
2123 function makeTameNodeByType(node, editable) { | 2125 function makeTameNodeByType(node, editable) { |
2124 switch (node.nodeType) { | 2126 switch (node.nodeType) { |
2125 case 1: // Element | 2127 case 1: // Element |
2126 var tagName = node.tagName.toLowerCase(); | 2128 var tagName = node.tagName.toLowerCase(); |
2127 if (tamingClassesByElement.hasOwnProperty(tagName + '$')) { | |
2128 // Known element with specialized taming class (e.g. <a> has an | |
2129 // href property). This is deliberately before the unsafe test; | |
2130 // for example, <script> has its own class even though it is | |
2131 // unsafe. | |
2132 return new (tamingClassesByElement[tagName + '$'])( | |
2133 node, editable); | |
2134 }· | |
2135 var schemaElem = htmlSchema.element(tagName); | 2129 var schemaElem = htmlSchema.element(tagName); |
2136 if (schemaElem.isVirtualizedElementName) { | 2130 if (schemaElem.allowed || tagName === 'script') { |
2137 // Virtualized unrecognized elements are generic | 2131 // <script> is specifically allowed because we make provisions |
2138 return new TameElement(node, editable, editable); | 2132 // for controlling its content and src. |
2139 } else if (schemaElem.allowed) { | 2133 var domInterfaceName = schemaElem.domInterface; |
2140 return new TameElement(node, editable, editable); | 2134 if (nodeTamers.hasOwnProperty(domInterfaceName)) { |
2135 return new nodeTamers[domInterfaceName]( | |
2136 node, editable, editable); | |
2137 } else { | |
2138 if (!nodeClassNoImplWarnings[domInterfaceName]) { | |
2139 nodeClassNoImplWarnings[domInterfaceName] = true; | |
2140 if (typeof console !== 'undefined') { | |
2141 console.warn("Domado: " + domInterfaceName + " is not " + | |
2142 "tamed; its specific properties/methods will not be " + | |
2143 "available on <" + | |
2144 htmlSchema.realToVirtualElementName(tagName) + ">."); | |
2145 } | |
2146 } | |
2147 return new TameElement(node, editable, editable); | |
2148 } | |
2141 } else { | 2149 } else { |
2142 // If an unrecognized or unsafe node, return a | 2150 // If an unrecognized or unsafe node, return a |
2143 // placeholder that doesn't prevent tree navigation, | 2151 // placeholder that doesn't prevent tree navigation, |
2144 // but that doesn't allow mutation or leak attribute | 2152 // but that doesn't allow mutation or leak attribute |
2145 // information. | 2153 // information. |
2146 return new TameOpaqueNode(node, editable); | 2154 return new TameOpaqueNode(node, editable); |
2147 } | 2155 } |
2148 case 2: // Attr | 2156 case 2: // Attr |
2149 // Cannot generically wrap since we must have access to the | 2157 // Cannot generically wrap since we must have access to the |
2150 // owner element | 2158 // owner element |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2544 arrayRemove(np(this).wrappedListeners, i, i); | 2552 arrayRemove(np(this).wrappedListeners, i, i); |
2545 break; | 2553 break; |
2546 } | 2554 } |
2547 } | 2555 } |
2548 if (!wrappedListener) { return; } | 2556 if (!wrappedListener) { return; } |
2549 bridal.removeEventListener( | 2557 bridal.removeEventListener( |
2550 np(this).feral, name, wrappedListener, useCapture); | 2558 np(this).feral, name, wrappedListener, useCapture); |
2551 } | 2559 } |
2552 | 2560 |
2553 // A map of tamed node classes, keyed by DOM Level 2 standard name, which | 2561 // A map of tamed node classes, keyed by DOM Level 2 standard name, which |
2554 // will be exposed to the client. | 2562 // will be exposed to the client (and are not usable as constructors). |
2555 var nodeClasses = {}; | 2563 var nodeClasses = {}; |
2556 | 2564 // Ditto, but the taming constructors instead of the useless ones. |
2557 // A map of tamed node constructors, keyed by HTML element name, which | 2565 var nodeTamers = {}; |
2558 // will be used by defaultTameNode. | |
2559 var tamingClassesByElement = {}; | |
2560 | 2566 |
2561 /** | 2567 /** |
2562 * This does three things: | 2568 * This does three things: |
2563 * | 2569 * |
2564 * Replace tamedCtor's prototype with one whose prototype is someSuper. | 2570 * Replace tamedCtor's prototype with one whose prototype is someSuper. |
2565 * | 2571 * |
2566 * Hide the constructor of the products of tamedCtor, replacing it with a | 2572 * Hide the constructor of the products of tamedCtor, replacing it with a |
2567 * function which just throws (but can still be used for instanceof | 2573 * function which just throws (but can still be used for instanceof |
2568 * checks). | 2574 * checks). |
2569 * | 2575 * |
2570 * Register the inert ctor under the given name if specified. | 2576 * Register the inert ctor under the given name if specified. |
2571 */ | 2577 */ |
2572 function inertCtor(tamedCtor, someSuper, opt_name) { | 2578 function inertCtor(tamedCtor, someSuper, opt_name) { |
2573 inherit(tamedCtor, someSuper); | 2579 inherit(tamedCtor, someSuper); |
2574 | 2580 |
2575 var inert = function() { | 2581 var inert = function() { |
2576 throw new TypeError('This constructor cannot be called directly.'); | 2582 throw new TypeError('This constructor cannot be called directly.'); |
2577 }; | 2583 }; |
2578 inert.prototype = tamedCtor.prototype; | 2584 inert.prototype = tamedCtor.prototype; |
2579 Object.freeze(inert); // not def, because inert.prototype must remain | 2585 Object.freeze(inert); // not def, because inert.prototype must remain |
2580 setOwn(tamedCtor.prototype, "constructor", inert); | 2586 setOwn(tamedCtor.prototype, "constructor", inert); |
2581 | 2587 |
2582 if (opt_name !== undefined) | 2588 if (opt_name !== undefined) { |
2583 nodeClasses[opt_name] = inert; | 2589 nodeClasses[opt_name] = inert; |
2590 nodeTamers[opt_name] = tamedCtor; | |
2591 } | |
2584 | 2592 |
2585 return inert; | 2593 return inert; |
2586 } | 2594 } |
2587 | 2595 |
2588 traceStartup("DT: about to make TameNode"); | 2596 traceStartup("DT: about to make TameNode"); |
2589 | 2597 |
2590 /** | 2598 /** |
2591 * Base class for a Node wrapper. Do not create directly -- use the | 2599 * Base class for a Node wrapper. Do not create directly -- use the |
2592 * tameNode factory instead. | 2600 * tameNode factory instead. |
2593 * | 2601 * |
(...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3503 if (ancestor === feralBody) { | 3511 if (ancestor === feralBody) { |
3504 return defaultTameNode(feralBody, np(this).editable); | 3512 return defaultTameNode(feralBody, np(this).editable); |
3505 } | 3513 } |
3506 } | 3514 } |
3507 return null; | 3515 return null; |
3508 } else { | 3516 } else { |
3509 return tameRelatedNode(feralOffsetParent, np(this).editable, | 3517 return tameRelatedNode(feralOffsetParent, np(this).editable, |
3510 defaultTameNode); | 3518 defaultTameNode); |
3511 } | 3519 } |
3512 }) | 3520 }) |
3513 } | 3521 }, |
3522 accessKey: NP.rw, | |
3523 tabIndex: NP.rw | |
3514 }); | 3524 }); |
3515 cajaVM.def(TameElement); // and its prototype | 3525 cajaVM.def(TameElement); // and its prototype |
3516 | 3526 |
3517 traceStartup("DT: starting defineElement"); | 3527 traceStartup("DT: starting defineElement"); |
3518 | 3528 |
3519 /** | 3529 /** |
3520 * Define a taming class for a subclass of HTMLElement. | 3530 * Define a taming class for a subclass of HTMLElement. |
3521 * | 3531 * |
3522 * @param {Array} record.superclass The tame superclass constructor | 3532 * @param {Array} record.superclass The tame superclass constructor |
3523 * (defaults to TameElement) with parameters (this, node, editable, | 3533 * (defaults to TameElement) with parameters (this, node, editable, |
3524 * childrenEditable, opt_proxyType). | 3534 * childrenEditable, opt_proxyType). |
3525 * @param {Array} record.names The element names which should be tamed | 3535 * @param {Array} record.names The element names which should be tamed |
3526 * using this class. | 3536 * using this class. |
3527 * @param {String} record.domClass The DOM-specified class name. | 3537 * @param {String} record.domClass The DOM-specified class name. |
3528 * @param {Object} record.properties The custom properties this class | 3538 * @param {Object} record.properties The custom properties this class |
3529 * should have (in the format accepted by definePropertiesAwesomely). | 3539 * should have (in the format accepted by definePropertiesAwesomely). |
3530 * @param {function} record.construct Code to invoke at the end of | 3540 * @param {function} record.construct Code to invoke at the end of |
3531 * construction; takes and returns self. | 3541 * construction; takes and returns self. |
3532 * @param {boolean} record.forceChildrenNotEditable Whether to force the | 3542 * @param {boolean} record.forceChildrenNotEditable Whether to force the |
3533 * childrenEditable flag to be false regardless of the value of | 3543 * childrenEditable flag to be false regardless of the value of |
3534 * editable. | 3544 * editable. |
3535 * @return {function} The constructor. | 3545 * @return {function} The constructor. |
3536 */ | 3546 */ |
3537 function defineElement(record) { | 3547 function defineElement(record) { |
3538 var superclass = record.superclass || TameElement; | 3548 var superclass = record.superclass || TameElement; |
3539 var proxyType = record.proxyType; | 3549 var proxyType = record.proxyType; |
3540 var construct = record.construct || identity; | 3550 var construct = record.construct || identity; |
3541 var virtualized = record.virtualized || false; | 3551 var shouldBeVirtualized = record.virtualized || false; |
3542 var forceChildrenNotEditable = record.forceChildrenNotEditable; | 3552 var forceChildrenNotEditable = record.forceChildrenNotEditable; |
3543 function TameSpecificElement(node, editable) { | 3553 function TameSpecificElement(node, editable, childrenEditable) { |
3554 var isVirtualized = htmlSchema.isVirtualizedElementName(node.tagName); | |
3555 if (!isVirtualized !== !shouldBeVirtualized) { | |
Jasvir
2012/11/06 04:52:25
A little !too !clever. ;)
kpreid2
2012/11/06 19:19:54
This is a standard formulation of boolean xor. Do
| |
3556 throw new Error("Domado internal inconsistency: " + node.tagName + | |
3557 " has inconsistent virtualization state with class " + | |
3558 record.domClass); | |
3559 } | |
3544 superclass.call(this, | 3560 superclass.call(this, |
3545 node, | 3561 node, |
3546 editable, | 3562 editable, |
3547 editable && !forceChildrenNotEditable, | 3563 childrenEditable && !forceChildrenNotEditable, |
3548 proxyType); | 3564 proxyType); |
3549 construct.call(this); | 3565 construct.call(this); |
3550 } | 3566 } |
3551 inertCtor(TameSpecificElement, superclass, record.domClass); | 3567 inertCtor(TameSpecificElement, superclass, record.domClass); |
3552 for (var i = 0; i < record.names.length; i++) { | |
3553 var name = record.names[+i]; | |
3554 if (!!virtualized !== !!htmlSchema.element(name).shouldVirtualize) { | |
3555 throw new Error("Domado internal inconsistency: " + name +· | |
3556 "has inconsistent virtualization flags"); | |
3557 } | |
3558 tamingClassesByElement[virtualToRealElementName(name) + '$'] = | |
3559 TameSpecificElement; | |
3560 } | |
3561 definePropertiesAwesomely(TameSpecificElement.prototype, | 3568 definePropertiesAwesomely(TameSpecificElement.prototype, |
3562 record.properties || {}); | 3569 record.properties || {}); |
3563 // Note: cajaVM.def will be applied to all registered node classes | 3570 // Note: cajaVM.def will be applied to all registered node classes |
3564 // later, so users of defineElement don't need to. | 3571 // later, so users of defineElement don't need to. |
3565 return TameSpecificElement; | 3572 return TameSpecificElement; |
3566 } | 3573 } |
3567 cajaVM.def(defineElement); | 3574 cajaVM.def(defineElement); |
3575 ······ | |
3576 /** | |
3577 * For elements which have no properties at all, but we want to define in | |
3578 * in order to be explicitly complete (suppress the no-implementation | |
3579 * warning). | |
3580 */ | |
3581 function defineTrivialElement(domClass) { | |
3582 return defineElement({domClass: domClass}); | |
3583 } | |
3568 | 3584 |
3569 defineElement({ | 3585 defineElement({ |
3570 names: ['a'], | |
3571 domClass: 'HTMLAnchorElement', | 3586 domClass: 'HTMLAnchorElement', |
3572 properties: { | 3587 properties: { |
3573 hash: NP.filter( | 3588 hash: NP.filter( |
3574 false, | 3589 false, |
3575 function (value) { return unsuffix(value, idSuffix, value); }, | 3590 function (value) { return unsuffix(value, idSuffix, value); }, |
3576 false, | 3591 false, |
3577 // TODO(felix8a): add suffix if href is self | 3592 // TODO(felix8a): add suffix if href is self |
3578 identity), | 3593 identity), |
3579 // TODO(felix8a): fragment rewriting? | 3594 // TODO(felix8a): fragment rewriting? |
3580 href: NP.filter(false, identity, true, identity) | 3595 href: NP.filter(false, identity, true, identity) |
3581 } | 3596 } |
3582 }); | 3597 }); |
3583 | 3598 |
3599 defineTrivialElement('HTMLBRElement'); | |
3600 | |
3584 var TameBodyElement = defineElement({ | 3601 var TameBodyElement = defineElement({ |
3585 names: ['body'], | |
3586 virtualized: true, | 3602 virtualized: true, |
3587 domClass: 'HTMLBodyElement' | 3603 domClass: 'HTMLBodyElement' |
3588 }); | 3604 }); |
3589 setOwn(TameBodyElement.prototype, 'setAttribute', nodeMethod( | 3605 setOwn(TameBodyElement.prototype, 'setAttribute', nodeMethod( |
3590 function (attrib, value) { | 3606 function (attrib, value) { |
3591 TameElement.prototype.setAttribute.call(this, attrib, value); | 3607 TameElement.prototype.setAttribute.call(this, attrib, value); |
3592 var attribName = String(attrib).toLowerCase(); | 3608 var attribName = String(attrib).toLowerCase(); |
3593 // Window event handlers are exposed as content attributes on <body> | 3609 // Window event handlers are exposed as content attributes on <body> |
3594 // and <frameset> | 3610 // and <frameset> |
3595 // <http://www.whatwg.org/specs/web-apps/current-work/multipage/webappap is.html#handler-window-onload> | 3611 // <http://www.whatwg.org/specs/web-apps/current-work/multipage/webappap is.html#handler-window-onload> |
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4225 // Returning undefined rather than null is closer to the spec | 4241 // Returning undefined rather than null is closer to the spec |
4226 // than throwing. | 4242 // than throwing. |
4227 return undefined; | 4243 return undefined; |
4228 throw new Error('Unapproved canvas contextId'); | 4244 throw new Error('Unapproved canvas contextId'); |
4229 } | 4245 } |
4230 }; | 4246 }; |
4231 definePropertiesAwesomely(TameCanvasElement.prototype, { | 4247 definePropertiesAwesomely(TameCanvasElement.prototype, { |
4232 height: NP.filter(false, identity, false, Number), | 4248 height: NP.filter(false, identity, false, Number), |
4233 width: NP.filter(false, identity, false, Number) | 4249 width: NP.filter(false, identity, false, Number) |
4234 }); | 4250 }); |
4235 | |
4236 tamingClassesByElement['canvas$'] = TameCanvasElement; | |
4237 })(); | 4251 })(); |
4238 | 4252 |
4239 traceStartup("DT: done with canvas"); | 4253 traceStartup("DT: done with canvas"); |
4240 | 4254 |
4255 defineTrivialElement('HTMLDListElement'); | |
4256 defineTrivialElement('HTMLDivElement'); | |
4257 | |
4241 function FormElementAndExpandoProxyHandler(target, editable, storage) { | 4258 function FormElementAndExpandoProxyHandler(target, editable, storage) { |
4242 ExpandoProxyHandler.call(this, target, editable, storage); | 4259 ExpandoProxyHandler.call(this, target, editable, storage); |
4243 } | 4260 } |
4244 inherit(FormElementAndExpandoProxyHandler, ExpandoProxyHandler); | 4261 inherit(FormElementAndExpandoProxyHandler, ExpandoProxyHandler); |
4245 setOwn(FormElementAndExpandoProxyHandler.prototype, | 4262 setOwn(FormElementAndExpandoProxyHandler.prototype, |
4246 'getOwnPropertyDescriptor', function (name) { | 4263 'getOwnPropertyDescriptor', function (name) { |
4247 if (name !== 'ident___' && | 4264 if (name !== 'ident___' && |
4248 Object.prototype.hasOwnProperty.call(this.target.elements, name)) { | 4265 Object.prototype.hasOwnProperty.call(this.target.elements, name)) { |
4249 return Object.getOwnPropertyDescriptor(this.target.elements, name); | 4266 return Object.getOwnPropertyDescriptor(this.target.elements, name); |
4250 } else { | 4267 } else { |
(...skipping 22 matching lines...) Expand all Loading... | |
4273 } else if (Object.prototype.hasOwnProperty.call( | 4290 } else if (Object.prototype.hasOwnProperty.call( |
4274 this.target.elements, name)) { | 4291 this.target.elements, name)) { |
4275 return false; | 4292 return false; |
4276 } else { | 4293 } else { |
4277 return ExpandoProxyHandler.prototype['delete'].call(this, name); | 4294 return ExpandoProxyHandler.prototype['delete'].call(this, name); |
4278 } | 4295 } |
4279 }); | 4296 }); |
4280 cajaVM.def(FormElementAndExpandoProxyHandler); | 4297 cajaVM.def(FormElementAndExpandoProxyHandler); |
4281 | 4298 |
4282 var TameFormElement = defineElement({ | 4299 var TameFormElement = defineElement({ |
4283 names: ['form'], | |
4284 domClass: 'HTMLFormElement', | 4300 domClass: 'HTMLFormElement', |
4285 proxyType: FormElementAndExpandoProxyHandler, | 4301 proxyType: FormElementAndExpandoProxyHandler, |
4286 properties: { | 4302 properties: { |
4287 action: NP.filterAttr(defaultToEmptyStr, String), | 4303 action: NP.filterAttr(defaultToEmptyStr, String), |
4288 elements: { | 4304 elements: { |
4289 enumerable: true, | 4305 enumerable: true, |
4290 get: nodeMethod(function () { | 4306 get: nodeMethod(function () { |
4291 return tameHTMLCollection( | 4307 return tameHTMLCollection( |
4292 np(this).feral.elements, np(this).editable, defaultTameNode); | 4308 np(this).feral.elements, np(this).editable, defaultTameNode); |
4293 }) | 4309 }) |
(...skipping 12 matching lines...) Expand all Loading... | |
4306 }); | 4322 }); |
4307 TameFormElement.prototype.submit = nodeMethod(function () { | 4323 TameFormElement.prototype.submit = nodeMethod(function () { |
4308 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } | 4324 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } |
4309 return np(this).feral.submit(); | 4325 return np(this).feral.submit(); |
4310 }); | 4326 }); |
4311 TameFormElement.prototype.reset = nodeMethod(function () { | 4327 TameFormElement.prototype.reset = nodeMethod(function () { |
4312 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } | 4328 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } |
4313 return np(this).feral.reset(); | 4329 return np(this).feral.reset(); |
4314 }); | 4330 }); |
4315 | 4331 |
4332 defineTrivialElement('HTMLHeadingElement'); | |
4333 defineTrivialElement('HTMLHRElement'); | |
4334 | |
4316 defineElement({ | 4335 defineElement({ |
4317 names: ['head'], | |
4318 virtualized: true, | 4336 virtualized: true, |
4319 domClass: 'HTMLHeadElement' | 4337 domClass: 'HTMLHeadElement' |
4320 }); | 4338 }); |
4321 | 4339 |
4322 defineElement({ | 4340 defineElement({ |
4323 names: ['html'], | |
4324 virtualized: true, | 4341 virtualized: true, |
4325 domClass: 'HTMLHtmlElement' | 4342 domClass: 'HTMLHtmlElement' |
4326 }); | 4343 }); |
4327 | 4344 |
4328 var P_blacklist = { | 4345 var P_blacklist = { |
4329 enumerable: true, | 4346 enumerable: true, |
4330 extendedAccessors: true, | 4347 extendedAccessors: true, |
4331 get: nodeMethod(function () { return undefined; }), | 4348 get: nodeMethod(function () { return undefined; }), |
4332 set: nodeMethod(function (value, prop) { | 4349 set: nodeMethod(function (value, prop) { |
4333 if (typeof console !== 'undefined') | 4350 if (typeof console !== 'undefined') |
4334 console.error('Cannot set the [', prop, '] property of an iframe.'); | 4351 console.error('Cannot set the [', prop, '] property of an iframe.'); |
4335 }) | 4352 }) |
4336 }; | 4353 }; |
4337 var TameIFrameElement = defineElement({ | 4354 var TameIFrameElement = defineElement({ |
4338 names: ['iframe'], | |
4339 domClass: 'HTMLIFrameElement', | 4355 domClass: 'HTMLIFrameElement', |
4340 construct: function () { | 4356 construct: function () { |
4341 np(this).childrenEditable = false; | 4357 np(this).childrenEditable = false; |
4342 }, | 4358 }, |
4343 properties: { | 4359 properties: { |
4344 align: { | 4360 align: { |
4345 enumerable: true, | 4361 enumerable: true, |
4346 get: nodeMethod(function () { | 4362 get: nodeMethod(function () { |
4347 return np(this).feral.align; | 4363 return np(this).feral.align; |
4348 }), | 4364 }), |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4396 if (attrLc !== 'name' && attrLc !== 'src') { | 4412 if (attrLc !== 'name' && attrLc !== 'src') { |
4397 return TameElement.prototype.setAttribute.call(this, attr, value); | 4413 return TameElement.prototype.setAttribute.call(this, attr, value); |
4398 } | 4414 } |
4399 if (typeof console !== 'undefined') | 4415 if (typeof console !== 'undefined') |
4400 console.error('Cannot set the [' + attrLc + | 4416 console.error('Cannot set the [' + attrLc + |
4401 '] attribute of an iframe.'); | 4417 '] attribute of an iframe.'); |
4402 return value; | 4418 return value; |
4403 })); | 4419 })); |
4404 | 4420 |
4405 var TameImageElement = defineElement({ | 4421 var TameImageElement = defineElement({ |
4406 names: ['img'], | |
4407 domClass: 'HTMLImageElement', | 4422 domClass: 'HTMLImageElement', |
4408 properties: { | 4423 properties: { |
4409 alt: NP.filterProp(String, String), | 4424 alt: NP.filterProp(String, String), |
4410 height: NP.filterProp(Number, Number), | 4425 height: NP.filterProp(Number, Number), |
4411 src: NP.filter(false, String, true, identity), | 4426 src: NP.filter(false, String, true, identity), |
4412 width: NP.filterProp(Number, Number) | 4427 width: NP.filterProp(Number, Number) |
4413 } | 4428 } |
4414 }); | 4429 }); |
4415 var featureTestImage = makeDOMAccessible(document.createElement('img')); | 4430 var featureTestImage = makeDOMAccessible(document.createElement('img')); |
4416 if ("naturalWidth" in featureTestImage) { | 4431 if ("naturalWidth" in featureTestImage) { |
4417 definePropertiesAwesomely(TameImageElement, { | 4432 definePropertiesAwesomely(TameImageElement, { |
4418 naturalHeight: NP.filterProp(Number, Number), | 4433 naturalHeight: NP.filterProp(Number, Number), |
4419 naturalWidth: NP.filterProp(Number, Number) | 4434 naturalWidth: NP.filterProp(Number, Number) |
4420 }); | 4435 }); |
4421 } | 4436 } |
4422 if ("complete" in featureTestImage) { | 4437 if ("complete" in featureTestImage) { |
4423 definePropertiesAwesomely(TameImageElement, { | 4438 definePropertiesAwesomely(TameImageElement, { |
4424 complete: NP.filterProp(Boolean, Boolean) | 4439 complete: NP.filterProp(Boolean, Boolean) |
4425 }); | 4440 }); |
4426 } | 4441 } |
4427 | 4442 |
4428 function toInt(x) { return x | 0; } | 4443 function toInt(x) { return x | 0; } |
4429 // TODO(kpreid): The conflation of these elements is partly nonsense. | 4444 var TameFormField = defineElement({ |
4430 // Split it into the appropriate narrow interfaces for each element. | 4445 properties: { |
4446 disabled: NP.rw, | |
4447 form: NP.related, | |
4448 maxLength: NP.rw, | |
4449 name: NP.rw, | |
4450 value: NP.filter( | |
4451 false, function (x) { return x == null ? null : String(x); }, | |
4452 false, function (x) { return x == null ? '' : '' + x; }) | |
4453 } | |
4454 }); | |
4455 ······ | |
4431 var TameInputElement = defineElement({ | 4456 var TameInputElement = defineElement({ |
4432 names: ['select', 'button', 'textarea', 'input'], | 4457 superclass: TameFormField, |
4433 domClass: 'HTMLInputElement', | 4458 domClass: 'HTMLInputElement', |
4434 properties: { | 4459 properties: { |
4435 checked: NP.filterProp(identity, Boolean), | 4460 checked: NP.filterProp(identity, Boolean), |
4436 defaultChecked: NP.rw, | 4461 defaultChecked: NP.rw, |
4437 value: NP.filter( | |
4438 false, function (x) { return x == null ? null : String(x); }, | |
4439 false, function (x) { return x == null ? '' : '' + x; }), | |
4440 defaultValue: NP.filter( | 4462 defaultValue: NP.filter( |
4441 false, function (x) { return x == null ? null : String(x); }, | 4463 false, function (x) { return x == null ? null : String(x); }, |
4442 false, function (x) { return x == null ? '' : '' + x; }), | 4464 false, function (x) { return x == null ? '' : '' + x; }), |
4443 form: NP.related, | |
4444 disabled: NP.rw, | |
4445 readOnly: NP.rw, | 4465 readOnly: NP.rw, |
4466 selectedIndex: NP.filterProp(identity, toInt), | |
4467 size: NP.rw, | |
4468 type: NP.rw | |
4469 } | |
4470 }); | |
4471 TameInputElement.prototype.select = nodeMethod(function () { | |
4472 np(this).feral.select(); | |
4473 }); | |
4474 | |
4475 defineElement({ | |
4476 superclass: TameFormField, | |
4477 domClass: 'HTMLButtonElement', | |
4478 properties: { | |
4479 type: NP.rw | |
4480 } | |
4481 }); | |
4482 | |
4483 defineElement({ | |
4484 superclass: TameFormField, | |
4485 domClass: 'HTMLSelectElement', | |
4486 properties: { | |
4487 multiple: NP.rw, | |
4446 options: { | 4488 options: { |
4447 enumerable: true, | 4489 enumerable: true, |
4448 get: nodeMethod(function () { | 4490 get: nodeMethod(function () { |
4449 return new TameOptionsList( | 4491 return new TameOptionsList( |
4450 np(this).feral.options, | 4492 np(this).feral.options, |
4451 np(this).editable, | 4493 np(this).editable, |
4452 defaultTameNode, 'name'); | 4494 defaultTameNode, 'name'); |
4453 }) | 4495 }) |
4454 }, | 4496 }, |
4455 selectedIndex: NP.filterProp(identity, toInt), | 4497 selectedIndex: NP.filterProp(identity, toInt), |
4456 name: NP.rw, | 4498 type: NP.ro |
4457 accessKey: NP.rw, | |
4458 tabIndex: NP.rw, | |
4459 maxLength: NP.rw, | |
4460 size: NP.rw, | |
4461 type: NP.rw, | |
4462 multiple: NP.rw, | |
4463 cols: NP.rw, | |
4464 rows: NP.rw | |
4465 } | 4499 } |
4466 }); | 4500 }); |
4467 TameInputElement.prototype.select = nodeMethod(function () { | |
4468 np(this).feral.select(); | |
4469 }); | |
4470 | 4501 |
4471 defineElement({ | 4502 defineElement({ |
4472 names: ['label'], | 4503 superclass: TameFormField, |
4504 domClass: 'HTMLTextAreaElement', | |
4505 properties: { | |
4506 type: NP.rw | |
4507 } | |
4508 }); | |
4509 | |
4510 defineElement({ | |
4473 domClass: 'HTMLLabelElement', | 4511 domClass: 'HTMLLabelElement', |
4474 properties: { | 4512 properties: { |
4475 htmlFor: NP.Rename("for", NP.filterAttr(identity, identity)) | 4513 htmlFor: NP.Rename("for", NP.filterAttr(identity, identity)) |
4476 } | 4514 } |
4477 }); | 4515 }); |
4478 | 4516 |
4479 defineElement({ | 4517 defineElement({ |
4480 names: ['option'], | |
4481 domClass: 'HTMLOptionElement', | 4518 domClass: 'HTMLOptionElement', |
4482 properties: { | 4519 properties: { |
4483 defaultSelected: NP.filterProp(Boolean, Boolean), | 4520 defaultSelected: NP.filterProp(Boolean, Boolean), |
4484 disabled: NP.filterProp(Boolean, Boolean), | 4521 disabled: NP.filterProp(Boolean, Boolean), |
4485 form: NP.related, | 4522 form: NP.related, |
4486 index: NP.filterProp(Number), | 4523 index: NP.filterProp(Number), |
4487 label: NP.filterProp(String, String), | 4524 label: NP.filterProp(String, String), |
4488 selected: NP.filterProp(Boolean, Boolean), | 4525 selected: NP.filterProp(Boolean, Boolean), |
4489 text: NP.filterProp(String, String), | 4526 text: NP.filterProp(String, String), |
4490 // TODO(kpreid): Justify these specialized filters. | 4527 // TODO(kpreid): Justify these specialized filters. |
4491 value: NP.filterProp( | 4528 value: NP.filterProp( |
4492 function (x) { return x == null ? null : String(x); }, | 4529 function (x) { return x == null ? null : String(x); }, |
4493 function (x) { return x == null ? '' : '' + x; }) | 4530 function (x) { return x == null ? '' : '' + x; }) |
4494 } | 4531 } |
4495 }); | 4532 }); |
4533 ······ | |
4534 defineTrivialElement('HTMLParagraphElement'); | |
4535 defineTrivialElement('HTMLPreElement'); | |
4496 | 4536 |
4497 function dynamicCodeDispatchMaker(that) { | 4537 function dynamicCodeDispatchMaker(that) { |
4498 window.cajaDynamicScriptCounter = | 4538 window.cajaDynamicScriptCounter = |
4499 window.cajaDynamicScriptCounter ? | 4539 window.cajaDynamicScriptCounter ? |
4500 window.cajaDynamicScriptCounter + 1 : 0; | 4540 window.cajaDynamicScriptCounter + 1 : 0; |
4501 var name = "caja_dynamic_script" + | 4541 var name = "caja_dynamic_script" + |
4502 window.cajaDynamicScriptCounter + '___'; | 4542 window.cajaDynamicScriptCounter + '___'; |
4503 window[name] = function() { | 4543 window[name] = function() { |
4504 try { | 4544 try { |
4505 if (that.src && | 4545 if (that.src && |
4506 'function' === typeof domicile.evaluateUntrustedExternalScript) { | 4546 'function' === typeof domicile.evaluateUntrustedExternalScript) { |
4507 domicile.evaluateUntrustedExternalScript(that.src); | 4547 domicile.evaluateUntrustedExternalScript(that.src); |
4508 } | 4548 } |
4509 } finally { | 4549 } finally { |
4510 window[name] = undefined; | 4550 window[name] = undefined; |
4511 } | 4551 } |
4512 }; | 4552 }; |
4513 return name + "();"; | 4553 return name + "();"; |
4514 } | 4554 } |
4515 | 4555 |
4516 var TameScriptElement = defineElement({ | 4556 var TameScriptElement = defineElement({ |
4517 names: ['script'], | |
4518 domClass: 'HTMLScriptElement', | 4557 domClass: 'HTMLScriptElement', |
4519 forceChildrenNotEditable: true, | 4558 forceChildrenNotEditable: true, |
4520 properties: { | 4559 properties: { |
4521 src: NP.filter(false, identity, true, identity) | 4560 src: NP.filter(false, identity, true, identity) |
4522 }, | 4561 }, |
4523 construct: function () { | 4562 construct: function () { |
4524 var script = np(this); | 4563 var script = np(this); |
4525 script.feral.appendChild( | 4564 script.feral.appendChild( |
4526 document.createTextNode( | 4565 document.createTextNode( |
4527 dynamicCodeDispatchMaker(script))); | 4566 dynamicCodeDispatchMaker(script))); |
4528 } | 4567 } |
4529 }); | 4568 }); |
4530 | 4569 |
4531 setOwn(TameScriptElement.prototype, 'setAttribute', nodeMethod( | 4570 setOwn(TameScriptElement.prototype, 'setAttribute', nodeMethod( |
4532 function (attrib, value) { | 4571 function (attrib, value) { |
4533 var feral = np(this).feral; | 4572 var feral = np(this).feral; |
4534 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } | 4573 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } |
4535 TameElement.prototype.setAttribute.call(this, attrib, value); | 4574 TameElement.prototype.setAttribute.call(this, attrib, value); |
4536 var attribName = String(attrib).toLowerCase(); | 4575 var attribName = String(attrib).toLowerCase(); |
4537 if ("src" === attribName) { | 4576 if ("src" === attribName) { |
4538 np(this).src = String(value); | 4577 np(this).src = String(value); |
4539 } | 4578 } |
4540 })); | 4579 })); |
4541 | 4580 |
4542 var TameTableCompElement = defineElement({ | 4581 defineTrivialElement('HTMLSpanElement'); |
4543 names: ['td', 'thead', 'tfoot', 'tbody', 'th'], | 4582 |
4583 defineElement({ | |
4584 domClass: 'HTMLTableColElement', | |
4585 properties: { | |
4586 align: NP.filterProp(identity, identity), | |
4587 vAlign: NP.filterProp(identity, identity) | |
4588 } | |
4589 }); | |
4590 ······ | |
4591 defineTrivialElement('HTMLCaptionElement'); | |
4592 ······ | |
4593 var TameTableCellElement = defineElement({ | |
4594 domClass: 'HTMLTableCellElement', | |
4544 properties: { | 4595 properties: { |
4545 colSpan: NP.filterProp(identity, identity), | 4596 colSpan: NP.filterProp(identity, identity), |
4597 rowSpan: NP.filterProp(identity, identity), | |
4598 cellIndex: NP.ro, | |
4599 noWrap: NP.filterProp(identity, identity) // HTML5 Obsolete | |
4600 } | |
4601 }); | |
4602 defineElement({ | |
4603 superclass: TameTableCellElement, | |
4604 domClass: 'HTMLTableDataCellElement' | |
4605 }); | |
4606 defineElement({ | |
4607 superclass: TameTableCellElement, | |
4608 domClass: 'HTMLTableHeaderCellElement' | |
4609 }); | |
4610 | |
4611 function requireIntIn(idx, min, max) { | |
4612 if (idx !== (idx | 0) || idx < min || idx > max) { | |
4613 throw new Error(INDEX_SIZE_ERROR); | |
4614 } | |
4615 } | |
4616 | |
4617 var TameTableRowElement = defineElement({ | |
4618 domClass: 'HTMLTableRowElement', | |
4619 properties: { | |
4546 cells: { | 4620 cells: { |
4547 // TODO(kpreid): It would be most pleasing to find a way to generali ze | 4621 // TODO(kpreid): It would be most pleasing to find a way to generali ze |
4548 // all the accessors which are of the form | 4622 // all the accessors which are of the form |
4549 // return new TameNodeList(np(this).feral...., ..., ...) | 4623 // return new TameNodeList(np(this).feral...., ..., ...) |
4550 enumerable: true, | 4624 enumerable: true, |
4551 get: nodeMethod(function () { | 4625 get: nodeMethod(function () { |
4552 return new TameNodeList( | 4626 return new TameNodeList( |
4553 np(this).feral.cells, np(this).editable, defaultTameNode); | 4627 np(this).feral.cells, np(this).editable, defaultTameNode); |
4554 }) | 4628 }) |
4555 }, | 4629 }, |
4556 cellIndex: NP.ro, | |
4557 rowSpan: NP.filterProp(identity, identity), | |
4558 rows: { | |
4559 enumerable: true, | |
4560 get: nodeMethod(function () { | |
4561 return new TameNodeList( | |
4562 np(this).feral.rows, np(this).editable, defaultTameNode); | |
4563 }) | |
4564 }, | |
4565 rowIndex: NP.ro, | 4630 rowIndex: NP.ro, |
4566 sectionRowIndex: NP.ro, | 4631 sectionRowIndex: NP.ro |
4567 align: NP.filterProp(identity, identity), | |
4568 vAlign: NP.filterProp(identity, identity), | |
4569 nowrap: NP.filterProp(identity, identity) | |
4570 } | 4632 } |
4571 }); | 4633 }); |
4572 TameTableCompElement.prototype.insertRow = nodeMethod(function (index) { | |
4573 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } | |
4574 requireIntIn(index, -1, np(this).feral.rows.length); | |
4575 return defaultTameNode(np(this).feral.insertRow(index), | |
4576 np(this).editable); | |
4577 }); | |
4578 TameTableCompElement.prototype.deleteRow = nodeMethod(function (index) { | |
4579 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } | |
4580 requireIntIn(index, -1, np(this).feral.rows.length); | |
4581 np(this).feral.deleteRow(index); | |
4582 }); | |
4583 | |
4584 function requireIntIn(idx, min, max) { | |
4585 if (idx !== (idx | 0) || idx < min || idx > max) { | |
4586 throw new Error(INDEX_SIZE_ERROR); | |
4587 } | |
4588 } | |
4589 | |
4590 var TameTableRowElement = defineElement({ | |
4591 superclass: TameTableCompElement, | |
4592 names: ['tr'], | |
4593 domClass: 'HTMLTableRowElement' | |
4594 }); | |
4595 TameTableRowElement.prototype.insertCell = nodeMethod(function (index) { | 4634 TameTableRowElement.prototype.insertCell = nodeMethod(function (index) { |
4596 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } | 4635 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } |
4597 requireIntIn(index, -1, np(this).feral.cells.length); | 4636 requireIntIn(index, -1, np(this).feral.cells.length); |
4598 return defaultTameNode( | 4637 return defaultTameNode( |
4599 np(this).feral.insertCell(index), | 4638 np(this).feral.insertCell(index), |
4600 np(this).editable); | 4639 np(this).editable); |
4601 }); | 4640 }); |
4602 TameTableRowElement.prototype.deleteCell = nodeMethod(function (index) { | 4641 TameTableRowElement.prototype.deleteCell = nodeMethod(function (index) { |
4603 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } | 4642 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } |
4604 requireIntIn(index, -1, np(this).feral.cells.length); | 4643 requireIntIn(index, -1, np(this).feral.cells.length); |
4605 np(this).feral.deleteCell(index); | 4644 np(this).feral.deleteCell(index); |
4606 }); | 4645 }); |
4607 | 4646 |
4647 var TameTableSectionElement = defineElement({ | |
4648 domClass: 'HTMLTableSectionElement', | |
4649 properties: { | |
4650 rows: { | |
4651 enumerable: true, | |
4652 get: nodeMethod(function () { | |
4653 return new TameNodeList( | |
4654 np(this).feral.rows, np(this).editable, defaultTameNode); | |
4655 }) | |
4656 } | |
4657 } | |
4658 }); | |
4659 TameTableSectionElement.prototype.insertRow = nodeMethod(function(index) { | |
4660 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } | |
4661 requireIntIn(index, -1, np(this).feral.rows.length); | |
4662 return defaultTameNode(np(this).feral.insertRow(index), | |
4663 np(this).editable); | |
4664 }); | |
4665 TameTableSectionElement.prototype.deleteRow = nodeMethod(function(index) { | |
4666 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } | |
4667 requireIntIn(index, -1, np(this).feral.rows.length); | |
4668 np(this).feral.deleteRow(index); | |
4669 }); | |
4670 | |
4608 var TameTableElement = defineElement({ | 4671 var TameTableElement = defineElement({ |
4609 superclass: TameTableCompElement, | 4672 superclass: TameTableSectionElement, // nonstandard but sound |
4610 names: ['table'], | |
4611 domClass: 'HTMLTableElement', | 4673 domClass: 'HTMLTableElement', |
4612 properties: { | 4674 properties: { |
4613 tBodies: { | 4675 tBodies: { |
4614 enumerable: true, | 4676 enumerable: true, |
4615 get: nodeMethod(function () { | 4677 get: nodeMethod(function () { |
4616 return new TameNodeList( | 4678 return new TameNodeList( |
4617 np(this).feral.tBodies, np(this).editable, defaultTameNode); | 4679 np(this).feral.tBodies, np(this).editable, defaultTameNode); |
4618 }) | 4680 }) |
4619 }, | 4681 }, |
4620 tHead: NP_tameDescendant, | 4682 tHead: NP_tameDescendant, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4654 return defaultTameNode(np(this).feral.insertRow(index), | 4716 return defaultTameNode(np(this).feral.insertRow(index), |
4655 np(this).editable); | 4717 np(this).editable); |
4656 }); | 4718 }); |
4657 TameTableElement.prototype.deleteRow = nodeMethod(function (index) { | 4719 TameTableElement.prototype.deleteRow = nodeMethod(function (index) { |
4658 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } | 4720 if (!np(this).editable) { throw new Error(NOT_EDITABLE); } |
4659 requireIntIn(index, -1, np(this).feral.rows.length); | 4721 requireIntIn(index, -1, np(this).feral.rows.length); |
4660 np(this).feral.deleteRow(index); | 4722 np(this).feral.deleteRow(index); |
4661 }); | 4723 }); |
4662 | 4724 |
4663 defineElement({ | 4725 defineElement({ |
4664 names: ['title'], | |
4665 virtualized: true, | 4726 virtualized: true, |
4666 domClass: 'HTMLTitleElement' | 4727 domClass: 'HTMLTitleElement' |
4667 }); | 4728 }); |
4729 ······ | |
4730 defineTrivialElement('HTMLUListElement'); | |
4668 | 4731 |
4669 traceStartup('DT: done with specific elements'); | 4732 traceStartup('DT: done with specific elements'); |
4670 | 4733 |
4671 // Oddball constructors. There are only two of these and we implement | 4734 // Oddball constructors. There are only two of these and we implement |
4672 // both. (Caveat: In actual browsers, new Image().constructor == Image | 4735 // both. (Caveat: In actual browsers, new Image().constructor == Image |
4673 // != HTMLImageElement. We don't implement that.) | 4736 // != HTMLImageElement. We don't implement that.) |
4674 ······ | 4737 ······ |
4675 // Per https://developer.mozilla.org/en-US/docs/DOM/Image as of 2012-09-24 | 4738 // Per https://developer.mozilla.org/en-US/docs/DOM/Image as of 2012-09-24 |
4676 function TameImageFun(width, height) { | 4739 function TameImageFun(width, height) { |
4677 var element = tameDocument.createElement('img'); | 4740 var element = tameDocument.createElement('img'); |
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5203 TameStyleConf.p(this).editable = editable; | 5266 TameStyleConf.p(this).editable = editable; |
5204 TameStyleConf.p(this).tameElement = tameEl; | 5267 TameStyleConf.p(this).tameElement = tameEl; |
5205 | 5268 |
5206 TameStyleConf.p(this).readByCanonicalName = function(canonName) { | 5269 TameStyleConf.p(this).readByCanonicalName = function(canonName) { |
5207 return String(style[canonName] || ''); | 5270 return String(style[canonName] || ''); |
5208 }; | 5271 }; |
5209 TameStyleConf.p(this).writeByCanonicalName = function(canonName, val) { | 5272 TameStyleConf.p(this).writeByCanonicalName = function(canonName, val) { |
5210 style[canonName] = val; | 5273 style[canonName] = val; |
5211 }; | 5274 }; |
5212 }; | 5275 }; |
5213 inertCtor(TameStyle, Object, 'Style'); | 5276 inertCtor(TameStyle, Object /*, 'Style'*/); |
5277 // cannot export lazily | |
5214 TameStyle.prototype.getPropertyValue = | 5278 TameStyle.prototype.getPropertyValue = |
5215 cajaVM.def(function (cssPropertyName) { | 5279 cajaVM.def(function (cssPropertyName) { |
5216 cssPropertyName = String(cssPropertyName || '').toLowerCase(); | 5280 cssPropertyName = String(cssPropertyName || '').toLowerCase(); |
5217 if (!allowProperty(cssPropertyName)) { return ''; } | 5281 if (!allowProperty(cssPropertyName)) { return ''; } |
5218 var canonName = allCssProperties.getCanonicalPropFromCss( | 5282 var canonName = allCssProperties.getCanonicalPropFromCss( |
5219 cssPropertyName); | 5283 cssPropertyName); |
5220 return TameStyleConf.p(this).readByCanonicalName(canonName); | 5284 return TameStyleConf.p(this).readByCanonicalName(canonName); |
5221 }); | 5285 }); |
5222 setOwn(TameStyle.prototype, "toString", cajaVM.def(function () { | 5286 setOwn(TameStyle.prototype, "toString", cajaVM.def(function () { |
5223 return '[domado object Style]'; | 5287 return '[domado object Style]'; |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5437 // bitmask of trace points | 5501 // bitmask of trace points |
5438 // 0x0001 plugin_dispatchEvent | 5502 // 0x0001 plugin_dispatchEvent |
5439 domicile.domitaTrace = 0; | 5503 domicile.domitaTrace = 0; |
5440 domicile.getDomitaTrace = cajaVM.def( | 5504 domicile.getDomitaTrace = cajaVM.def( |
5441 function () { return domicile.domitaTrace; } | 5505 function () { return domicile.domitaTrace; } |
5442 ); | 5506 ); |
5443 domicile.setDomitaTrace = cajaVM.def( | 5507 domicile.setDomitaTrace = cajaVM.def( |
5444 function (x) { domicile.domitaTrace = x; } | 5508 function (x) { domicile.domitaTrace = x; } |
5445 ); | 5509 ); |
5446 | 5510 |
5511 // Freeze exported classes. Must occur before TameHTMLDocument is | |
5512 // instantiated. | |
5513 for (var name in nodeClasses) { | |
5514 var ctor = nodeClasses[name]; | |
5515 cajaVM.def(ctor); // and its prototype | |
5516 } | |
5517 Object.freeze(nodeClasses); | |
5518 // fail hard if late-added item wouldn't be frozen | |
5519 | |
5447 // Location object -- used by Document and Window and so must be created | 5520 // Location object -- used by Document and Window and so must be created |
5448 // before each. | 5521 // before each. |
5449 function TameLocation() { | 5522 function TameLocation() { |
5450 // TODO(mikesamuel): figure out a mechanism by which the container can | 5523 // TODO(mikesamuel): figure out a mechanism by which the container can |
5451 // specify the gadget's apparent URL. | 5524 // specify the gadget's apparent URL. |
5452 // See http://www.whatwg.org/specs/web-apps/current-work/multipage/histo ry.html#location0 | 5525 // See http://www.whatwg.org/specs/web-apps/current-work/multipage/histo ry.html#location0 |
5453 var tameLocation = this; | 5526 var tameLocation = this; |
5454 function defineLocationField(f, dflt) { | 5527 function defineLocationField(f, dflt) { |
5455 Object.defineProperty(tameLocation, f, { | 5528 Object.defineProperty(tameLocation, f, { |
5456 configurable: false, | 5529 configurable: false, |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5732 Object.freeze(tameDefaultView); | 5805 Object.freeze(tameDefaultView); |
5733 | 5806 |
5734 if (np(tameDocument).editable) { | 5807 if (np(tameDocument).editable) { |
5735 tameDocument.defaultView = tameDefaultView; | 5808 tameDocument.defaultView = tameDefaultView; |
5736 | 5809 |
5737 // Hook for document.write support. | 5810 // Hook for document.write support. |
5738 domicile.sanitizeAttrs = sanitizeAttrs; | 5811 domicile.sanitizeAttrs = sanitizeAttrs; |
5739 } | 5812 } |
5740 | 5813 |
5741 // Iterate over all node classes, assigning them to the Window object | 5814 // Iterate over all node classes, assigning them to the Window object |
5742 // under their DOM Level 2 standard name. Also freeze. | 5815 // under their DOM Level 2 standard name. They have been frozen above. |
5743 for (var name in nodeClasses) { | 5816 for (var name in nodeClasses) { |
5744 var ctor = nodeClasses[name]; | 5817 var ctor = nodeClasses[name]; |
5745 cajaVM.def(ctor); // and its prototype | |
5746 cajaVM.def(ctor.prototype); | |
5747 Object.defineProperty(tameWindow, name, { | 5818 Object.defineProperty(tameWindow, name, { |
5748 enumerable: true, | 5819 enumerable: true, |
5749 configurable: true, | 5820 configurable: true, |
5750 writable: true, | 5821 writable: true, |
5751 value: ctor | 5822 value: ctor |
5752 }); | 5823 }); |
5753 } | 5824 } |
5754 | 5825 |
5755 // TODO(ihab.awad): Build a more sophisticated virtual class hierarchy by | 5826 // TODO(ihab.awad): Build a more sophisticated virtual class hierarchy by |
5756 // creating a table of actual subclasses and instantiating tame nodes by | 5827 // creating a table of actual subclasses and instantiating tame nodes by |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5946 plugin_dispatchToHandler: plugin_dispatchToHandler, | 6017 plugin_dispatchToHandler: plugin_dispatchToHandler, |
5947 getDomicileForWindow: windowToDomicile.get.bind(windowToDomicile) | 6018 getDomicileForWindow: windowToDomicile.get.bind(windowToDomicile) |
5948 }); | 6019 }); |
5949 }); | 6020 }); |
5950 })(); | 6021 })(); |
5951 | 6022 |
5952 // Exports for closure compiler. | 6023 // Exports for closure compiler. |
5953 if (typeof window !== 'undefined') { | 6024 if (typeof window !== 'undefined') { |
5954 window['Domado'] = Domado; | 6025 window['Domado'] = Domado; |
5955 } | 6026 } |
OLD | NEW |