OLD | NEW |
1 // Copyright (C) 2008-2012 Google Inc. | 1 // Copyright (C) 2008-2012 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 2318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2329 * Return the object which stores expando properties for a given | 2329 * Return the object which stores expando properties for a given |
2330 * host DOM node. | 2330 * host DOM node. |
2331 */ | 2331 */ |
2332 function getNodeExpandoStorage(node) { | 2332 function getNodeExpandoStorage(node) { |
2333 var s = nodeExpandos.get(node); | 2333 var s = nodeExpandos.get(node); |
2334 if (s === undefined) { | 2334 if (s === undefined) { |
2335 nodeExpandos.set(node, s = {}); | 2335 nodeExpandos.set(node, s = {}); |
2336 } | 2336 } |
2337 return s; | 2337 return s; |
2338 } | 2338 } |
| 2339 ······ |
| 2340 var nodeClassNoImplWarnings = {}; |
2339 | 2341 |
2340 function makeTameNodeByType(node) { | 2342 function makeTameNodeByType(node) { |
2341 switch (node.nodeType) { | 2343 switch (node.nodeType) { |
2342 case 1: // Element | 2344 case 1: // Element |
2343 var tagName = node.tagName.toLowerCase(); | 2345 var tagName = node.tagName.toLowerCase(); |
2344 if (tamingClassesByElement.hasOwnProperty(tagName + '$')) { | |
2345 // Known element with specialized taming class (e.g. <a> has an | |
2346 // href property). This is deliberately before the unsafe test; | |
2347 // for example, <script> has its own class even though it is | |
2348 // unsafe. | |
2349 return new (tamingClassesByElement[tagName + '$'])(node); | |
2350 } | |
2351 var schemaElem = htmlSchema.element(tagName); | 2346 var schemaElem = htmlSchema.element(tagName); |
2352 if (schemaElem.isVirtualizedElementName) { | 2347 if (schemaElem.allowed || tagName === 'script') { |
2353 // Virtualized unrecognized elements are generic | 2348 // <script> is specifically allowed because we make provisions |
2354 return new TameElement(node); | 2349 // for controlling its content and src. |
2355 } else if (schemaElem.allowed) { | 2350 var domInterfaceName = schemaElem.domInterface; |
2356 return new TameElement(node); | 2351 if (nodeTamers.hasOwnProperty(domInterfaceName)) { |
| 2352 return new nodeTamers[domInterfaceName](node); |
| 2353 } else { |
| 2354 if (!nodeClassNoImplWarnings[domInterfaceName]) { |
| 2355 nodeClassNoImplWarnings[domInterfaceName] = true; |
| 2356 if (typeof console !== 'undefined') { |
| 2357 console.warn("Domado: " + domInterfaceName + " is not " + |
| 2358 "tamed; its specific properties/methods will not be " + |
| 2359 "available on <" + |
| 2360 htmlSchema.realToVirtualElementName(tagName) + ">."); |
| 2361 } |
| 2362 } |
| 2363 return new TameElement(node); |
| 2364 } |
2357 } else { | 2365 } else { |
2358 // If an unrecognized or unsafe node, return a | 2366 // If an unrecognized or unsafe node, return a |
2359 // placeholder that doesn't prevent tree navigation, | 2367 // placeholder that doesn't prevent tree navigation, |
2360 // but that doesn't allow mutation or leak attribute | 2368 // but that doesn't allow mutation or leak attribute |
2361 // information. | 2369 // information. |
2362 return new TameOpaqueNode(node); | 2370 return new TameOpaqueNode(node); |
2363 } | 2371 } |
2364 case 2: // Attr | 2372 case 2: // Attr |
2365 // Cannot generically wrap since we must have access to the | 2373 // Cannot generically wrap since we must have access to the |
2366 // owner element | 2374 // owner element |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2870 arrayRemove(np(this).wrappedListeners, i, i); | 2878 arrayRemove(np(this).wrappedListeners, i, i); |
2871 break; | 2879 break; |
2872 } | 2880 } |
2873 } | 2881 } |
2874 if (!wrappedListener) { return; } | 2882 if (!wrappedListener) { return; } |
2875 bridal.removeEventListener( | 2883 bridal.removeEventListener( |
2876 np(this).feral, name, wrappedListener, useCapture); | 2884 np(this).feral, name, wrappedListener, useCapture); |
2877 } | 2885 } |
2878 | 2886 |
2879 // A map of tamed node classes, keyed by DOM Level 2 standard name, which | 2887 // A map of tamed node classes, keyed by DOM Level 2 standard name, which |
2880 // will be exposed to the client. | 2888 // will be exposed to the client (and are not usable as constructors). |
2881 var nodeClasses = {}; | 2889 var nodeClasses = {}; |
2882 | 2890 // Ditto, but the taming constructors instead of the useless ones. |
2883 // A map of tamed node constructors, keyed by HTML element name, which | 2891 var nodeTamers = {}; |
2884 // will be used by defaultTameNode. | |
2885 var tamingClassesByElement = {}; | |
2886 | 2892 |
2887 /** | 2893 /** |
2888 * This does three things: | 2894 * This does three things: |
2889 * | 2895 * |
2890 * Replace tamedCtor's prototype with one whose prototype is someSuper. | 2896 * Replace tamedCtor's prototype with one whose prototype is someSuper. |
2891 * | 2897 * |
2892 * Hide the constructor of the products of tamedCtor, replacing it with a | 2898 * Hide the constructor of the products of tamedCtor, replacing it with a |
2893 * function which just throws (but can still be used for instanceof | 2899 * function which just throws (but can still be used for instanceof |
2894 * checks). | 2900 * checks). |
2895 * | 2901 * |
2896 * Register the inert ctor under the given name if specified. | 2902 * Register the inert ctor under the given name if specified. |
2897 */ | 2903 */ |
2898 function inertCtor(tamedCtor, someSuper, opt_name) { | 2904 function inertCtor(tamedCtor, someSuper, opt_name) { |
2899 inherit(tamedCtor, someSuper); | 2905 inherit(tamedCtor, someSuper); |
2900 | 2906 |
2901 var inert = function() { | 2907 var inert = function() { |
2902 throw new TypeError('This constructor cannot be called directly.'); | 2908 throw new TypeError('This constructor cannot be called directly.'); |
2903 }; | 2909 }; |
2904 inert.prototype = tamedCtor.prototype; | 2910 inert.prototype = tamedCtor.prototype; |
2905 Object.freeze(inert); // not def, because inert.prototype must remain | 2911 Object.freeze(inert); // not def, because inert.prototype must remain |
2906 setOwn(tamedCtor.prototype, "constructor", inert); | 2912 setOwn(tamedCtor.prototype, "constructor", inert); |
2907 | 2913 |
2908 if (opt_name !== undefined) | 2914 if (opt_name !== undefined) { |
2909 nodeClasses[opt_name] = inert; | 2915 nodeClasses[opt_name] = inert; |
| 2916 nodeTamers[opt_name] = tamedCtor; |
| 2917 } |
2910 | 2918 |
2911 return inert; | 2919 return inert; |
2912 } | 2920 } |
2913 | 2921 |
2914 traceStartup("DT: about to make TameNode"); | 2922 traceStartup("DT: about to make TameNode"); |
2915 | 2923 |
2916 /** | 2924 /** |
2917 * Base class for a Node wrapper. Do not create directly -- use the | 2925 * Base class for a Node wrapper. Do not create directly -- use the |
2918 * tameNode factory instead. | 2926 * tameNode factory instead. |
2919 * | 2927 * |
(...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3778 ancestor = makeDOMAccessible(ancestor.parentNode)) { | 3786 ancestor = makeDOMAccessible(ancestor.parentNode)) { |
3779 if (ancestor === feralBody) { | 3787 if (ancestor === feralBody) { |
3780 return defaultTameNode(feralBody); | 3788 return defaultTameNode(feralBody); |
3781 } | 3789 } |
3782 } | 3790 } |
3783 return null; | 3791 return null; |
3784 } else { | 3792 } else { |
3785 return tameRelatedNode(feralOffsetParent, defaultTameNode); | 3793 return tameRelatedNode(feralOffsetParent, defaultTameNode); |
3786 } | 3794 } |
3787 }) | 3795 }) |
3788 } | 3796 }, |
| 3797 accessKey: NP.rw, |
| 3798 tabIndex: NP.rw |
3789 }); | 3799 }); |
3790 cajaVM.def(TameElement); // and its prototype | 3800 cajaVM.def(TameElement); // and its prototype |
3791 | 3801 |
3792 traceStartup("DT: starting defineElement"); | 3802 traceStartup("DT: starting defineElement"); |
3793 | 3803 |
3794 /** | 3804 /** |
3795 * Define a taming class for a subclass of HTMLElement. | 3805 * Define a taming class for a subclass of HTMLElement. |
3796 * | 3806 * |
3797 * @param {Array} record.superclass The tame superclass constructor | 3807 * @param {Array} record.superclass The tame superclass constructor |
3798 * (defaults to TameElement) with parameters (this, node, policy, | 3808 * (defaults to TameElement) with parameters (this, node, policy, |
3799 * opt_proxyType). | 3809 * opt_proxyType). |
3800 * @param {Array} record.names The element names which should be tamed | 3810 * @param {Array} record.names The element names which should be tamed |
3801 * using this class. | 3811 * using this class. |
3802 * @param {String} record.domClass The DOM-specified class name. | 3812 * @param {String} record.domClass The DOM-specified class name. |
3803 * @param {Object} record.properties The custom properties this class | 3813 * @param {Object} record.properties The custom properties this class |
3804 * should have (in the format accepted by definePropertiesAwesomely). | 3814 * should have (in the format accepted by definePropertiesAwesomely). |
3805 * @param {function} record.construct Code to invoke at the end of | 3815 * @param {function} record.construct Code to invoke at the end of |
3806 * construction; takes and returns self. | 3816 * construction; takes and returns self. |
3807 * @param {boolean} record.forceChildrenNotEditable Whether to force the | 3817 * @param {boolean} record.forceChildrenNotEditable Whether to force the |
3808 * child node list and child nodes to not be mutable. | 3818 * child node list and child nodes to not be mutable. |
3809 * @return {function} The constructor. | 3819 * @return {function} The constructor. |
3810 */ | 3820 */ |
3811 function defineElement(record) { | 3821 function defineElement(record) { |
3812 var superclass = record.superclass || TameElement; | 3822 var superclass = record.superclass || TameElement; |
3813 var proxyType = record.proxyType; | 3823 var proxyType = record.proxyType; |
3814 var construct = record.construct || identity; | 3824 var construct = record.construct || identity; |
3815 var virtualized = record.virtualized || false; | 3825 var shouldBeVirtualized = "virtualized" in record |
| 3826 ? record.virtualized : false; |
3816 var opt_policy = record.forceChildrenNotEditable | 3827 var opt_policy = record.forceChildrenNotEditable |
3817 ? nodePolicyReadOnlyChildren : null; | 3828 ? nodePolicyReadOnlyChildren : null; |
3818 function TameSpecificElement(node) { | 3829 function TameSpecificElement(node) { |
| 3830 var isVirtualized = htmlSchema.isVirtualizedElementName(node.tagName); |
| 3831 if (shouldBeVirtualized !== null && |
| 3832 !isVirtualized !== !shouldBeVirtualized) { |
| 3833 throw new Error("Domado internal inconsistency: " + node.tagName + |
| 3834 " has inconsistent virtualization state with class " + |
| 3835 record.domClass); |
| 3836 } |
3819 superclass.call(this, node, opt_policy, proxyType); | 3837 superclass.call(this, node, opt_policy, proxyType); |
3820 construct.call(this); | 3838 construct.call(this); |
3821 } | 3839 } |
3822 inertCtor(TameSpecificElement, superclass, record.domClass); | 3840 inertCtor(TameSpecificElement, superclass, record.domClass); |
3823 for (var i = 0; i < record.names.length; i++) { | |
3824 var name = record.names[+i]; | |
3825 if (!!virtualized !== !!htmlSchema.element(name).shouldVirtualize) { | |
3826 throw new Error("Domado internal inconsistency: " + name +· | |
3827 "has inconsistent virtualization flags"); | |
3828 } | |
3829 tamingClassesByElement[virtualToRealElementName(name) + '$'] = | |
3830 TameSpecificElement; | |
3831 } | |
3832 definePropertiesAwesomely(TameSpecificElement.prototype, | 3841 definePropertiesAwesomely(TameSpecificElement.prototype, |
3833 record.properties || {}); | 3842 record.properties || {}); |
3834 // Note: cajaVM.def will be applied to all registered node classes | 3843 // Note: cajaVM.def will be applied to all registered node classes |
3835 // later, so users of defineElement don't need to. | 3844 // later, so users of defineElement don't need to. |
3836 return TameSpecificElement; | 3845 return TameSpecificElement; |
3837 } | 3846 } |
3838 cajaVM.def(defineElement); | 3847 cajaVM.def(defineElement); |
| 3848 ······ |
| 3849 /** |
| 3850 * For elements which have no properties at all, but we want to define in |
| 3851 * in order to be explicitly complete (suppress the no-implementation |
| 3852 * warning). |
| 3853 */ |
| 3854 function defineTrivialElement(domClass) { |
| 3855 return defineElement({domClass: domClass}); |
| 3856 } |
3839 | 3857 |
3840 defineElement({ | 3858 defineElement({ |
3841 names: ['a'], | |
3842 domClass: 'HTMLAnchorElement', | 3859 domClass: 'HTMLAnchorElement', |
3843 properties: { | 3860 properties: { |
3844 hash: NP.filter( | 3861 hash: NP.filter( |
3845 false, | 3862 false, |
3846 function (value) { return unsuffix(value, idSuffix, value); }, | 3863 function (value) { return unsuffix(value, idSuffix, value); }, |
3847 false, | 3864 false, |
3848 // TODO(felix8a): add suffix if href is self | 3865 // TODO(felix8a): add suffix if href is self |
3849 identity), | 3866 identity), |
3850 // TODO(felix8a): fragment rewriting? | 3867 // TODO(felix8a): fragment rewriting? |
3851 href: NP.filter(false, identity, true, identity) | 3868 href: NP.filter(false, identity, true, identity) |
3852 } | 3869 } |
3853 }); | 3870 }); |
3854 | 3871 |
| 3872 defineTrivialElement('HTMLBRElement'); |
| 3873 |
3855 var TameBodyElement = defineElement({ | 3874 var TameBodyElement = defineElement({ |
3856 names: ['body'], | |
3857 virtualized: true, | 3875 virtualized: true, |
3858 domClass: 'HTMLBodyElement' | 3876 domClass: 'HTMLBodyElement' |
3859 }); | 3877 }); |
3860 setOwn(TameBodyElement.prototype, 'setAttribute', nodeMethod( | 3878 setOwn(TameBodyElement.prototype, 'setAttribute', nodeMethod( |
3861 function (attrib, value) { | 3879 function (attrib, value) { |
3862 TameElement.prototype.setAttribute.call(this, attrib, value); | 3880 TameElement.prototype.setAttribute.call(this, attrib, value); |
3863 var attribName = String(attrib).toLowerCase(); | 3881 var attribName = String(attrib).toLowerCase(); |
3864 // Window event handlers are exposed as content attributes on <body> | 3882 // Window event handlers are exposed as content attributes on <body> |
3865 // and <frameset> | 3883 // and <frameset> |
3866 // <http://www.whatwg.org/specs/web-apps/current-work/multipage/webappap
is.html#handler-window-onload> | 3884 // <http://www.whatwg.org/specs/web-apps/current-work/multipage/webappap
is.html#handler-window-onload> |
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4493 // Returning undefined rather than null is closer to the spec | 4511 // Returning undefined rather than null is closer to the spec |
4494 // than throwing. | 4512 // than throwing. |
4495 return undefined; | 4513 return undefined; |
4496 throw new Error('Unapproved canvas contextId'); | 4514 throw new Error('Unapproved canvas contextId'); |
4497 } | 4515 } |
4498 }; | 4516 }; |
4499 definePropertiesAwesomely(TameCanvasElement.prototype, { | 4517 definePropertiesAwesomely(TameCanvasElement.prototype, { |
4500 height: NP.filter(false, identity, false, Number), | 4518 height: NP.filter(false, identity, false, Number), |
4501 width: NP.filter(false, identity, false, Number) | 4519 width: NP.filter(false, identity, false, Number) |
4502 }); | 4520 }); |
4503 | |
4504 tamingClassesByElement['canvas$'] = TameCanvasElement; | |
4505 })(); | 4521 })(); |
4506 | 4522 |
4507 traceStartup("DT: done with canvas"); | 4523 traceStartup("DT: done with canvas"); |
4508 | 4524 |
| 4525 defineTrivialElement('HTMLDListElement'); |
| 4526 defineTrivialElement('HTMLDivElement'); |
| 4527 |
4509 function FormElementAndExpandoProxyHandler(target, editable, storage) { | 4528 function FormElementAndExpandoProxyHandler(target, editable, storage) { |
4510 ExpandoProxyHandler.call(this, target, editable, storage); | 4529 ExpandoProxyHandler.call(this, target, editable, storage); |
4511 } | 4530 } |
4512 inherit(FormElementAndExpandoProxyHandler, ExpandoProxyHandler); | 4531 inherit(FormElementAndExpandoProxyHandler, ExpandoProxyHandler); |
4513 setOwn(FormElementAndExpandoProxyHandler.prototype, | 4532 setOwn(FormElementAndExpandoProxyHandler.prototype, |
4514 'getOwnPropertyDescriptor', function (name) { | 4533 'getOwnPropertyDescriptor', function (name) { |
4515 if (name !== 'ident___' && | 4534 if (name !== 'ident___' && |
4516 Object.prototype.hasOwnProperty.call(this.target.elements, name)) { | 4535 Object.prototype.hasOwnProperty.call(this.target.elements, name)) { |
4517 return Object.getOwnPropertyDescriptor(this.target.elements, name); | 4536 return Object.getOwnPropertyDescriptor(this.target.elements, name); |
4518 } else { | 4537 } else { |
(...skipping 22 matching lines...) Expand all Loading... |
4541 } else if (Object.prototype.hasOwnProperty.call( | 4560 } else if (Object.prototype.hasOwnProperty.call( |
4542 this.target.elements, name)) { | 4561 this.target.elements, name)) { |
4543 return false; | 4562 return false; |
4544 } else { | 4563 } else { |
4545 return ExpandoProxyHandler.prototype['delete'].call(this, name); | 4564 return ExpandoProxyHandler.prototype['delete'].call(this, name); |
4546 } | 4565 } |
4547 }); | 4566 }); |
4548 cajaVM.def(FormElementAndExpandoProxyHandler); | 4567 cajaVM.def(FormElementAndExpandoProxyHandler); |
4549 | 4568 |
4550 var TameFormElement = defineElement({ | 4569 var TameFormElement = defineElement({ |
4551 names: ['form'], | |
4552 domClass: 'HTMLFormElement', | 4570 domClass: 'HTMLFormElement', |
4553 proxyType: FormElementAndExpandoProxyHandler, | 4571 proxyType: FormElementAndExpandoProxyHandler, |
4554 properties: { | 4572 properties: { |
4555 action: NP.filterAttr(defaultToEmptyStr, String), | 4573 action: NP.filterAttr(defaultToEmptyStr, String), |
4556 elements: { | 4574 elements: { |
4557 enumerable: true, | 4575 enumerable: true, |
4558 get: nodeMethod(function () { | 4576 get: nodeMethod(function () { |
4559 return tameHTMLCollection( | 4577 return tameHTMLCollection( |
4560 np(this).feral.elements, defaultTameNode); | 4578 np(this).feral.elements, defaultTameNode); |
4561 }) | 4579 }) |
(...skipping 13 matching lines...) Expand all Loading... |
4575 // TODO(felix8a): need to test handlingUserAction. | 4593 // TODO(felix8a): need to test handlingUserAction. |
4576 TameFormElement.prototype.submit = nodeMethod(function () { | 4594 TameFormElement.prototype.submit = nodeMethod(function () { |
4577 np(this).policy.requireEditable(); | 4595 np(this).policy.requireEditable(); |
4578 return domicile.handlingUserAction && np(this).feral.submit(); | 4596 return domicile.handlingUserAction && np(this).feral.submit(); |
4579 }); | 4597 }); |
4580 TameFormElement.prototype.reset = nodeMethod(function () { | 4598 TameFormElement.prototype.reset = nodeMethod(function () { |
4581 np(this).policy.requireEditable(); | 4599 np(this).policy.requireEditable(); |
4582 return np(this).feral.reset(); | 4600 return np(this).feral.reset(); |
4583 }); | 4601 }); |
4584 | 4602 |
| 4603 defineTrivialElement('HTMLHeadingElement'); |
| 4604 defineTrivialElement('HTMLHRElement'); |
| 4605 |
4585 defineElement({ | 4606 defineElement({ |
4586 names: ['head'], | |
4587 virtualized: true, | 4607 virtualized: true, |
4588 domClass: 'HTMLHeadElement' | 4608 domClass: 'HTMLHeadElement' |
4589 }); | 4609 }); |
4590 | 4610 |
4591 defineElement({ | 4611 defineElement({ |
4592 names: ['html'], | |
4593 virtualized: true, | 4612 virtualized: true, |
4594 domClass: 'HTMLHtmlElement' | 4613 domClass: 'HTMLHtmlElement' |
4595 }); | 4614 }); |
4596 | 4615 |
4597 var P_blacklist = { | 4616 var P_blacklist = { |
4598 enumerable: true, | 4617 enumerable: true, |
4599 extendedAccessors: true, | 4618 extendedAccessors: true, |
4600 get: nodeMethod(function () { return undefined; }), | 4619 get: nodeMethod(function () { return undefined; }), |
4601 set: nodeMethod(function (value, prop) { | 4620 set: nodeMethod(function (value, prop) { |
4602 if (typeof console !== 'undefined') | 4621 if (typeof console !== 'undefined') |
4603 console.error('Cannot set the [', prop, '] property of an iframe.'); | 4622 console.error('Cannot set the [', prop, '] property of an iframe.'); |
4604 }) | 4623 }) |
4605 }; | 4624 }; |
4606 var TameIFrameElement = defineElement({ | 4625 var TameIFrameElement = defineElement({ |
4607 names: ['iframe'], | |
4608 domClass: 'HTMLIFrameElement', | 4626 domClass: 'HTMLIFrameElement', |
4609 construct: function () { | 4627 construct: function () { |
4610 np(this).childrenEditable = false; | 4628 np(this).childrenEditable = false; |
4611 }, | 4629 }, |
4612 properties: { | 4630 properties: { |
4613 align: { | 4631 align: { |
4614 enumerable: true, | 4632 enumerable: true, |
4615 get: nodeMethod(function () { | 4633 get: nodeMethod(function () { |
4616 return np(this).feral.align; | 4634 return np(this).feral.align; |
4617 }), | 4635 }), |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4666 if (attrLc !== 'name' && attrLc !== 'src') { | 4684 if (attrLc !== 'name' && attrLc !== 'src') { |
4667 return TameElement.prototype.setAttribute.call(this, attr, value); | 4685 return TameElement.prototype.setAttribute.call(this, attr, value); |
4668 } | 4686 } |
4669 if (typeof console !== 'undefined') | 4687 if (typeof console !== 'undefined') |
4670 console.error('Cannot set the [' + attrLc + | 4688 console.error('Cannot set the [' + attrLc + |
4671 '] attribute of an iframe.'); | 4689 '] attribute of an iframe.'); |
4672 return value; | 4690 return value; |
4673 })); | 4691 })); |
4674 | 4692 |
4675 var TameImageElement = defineElement({ | 4693 var TameImageElement = defineElement({ |
4676 names: ['img'], | |
4677 domClass: 'HTMLImageElement', | 4694 domClass: 'HTMLImageElement', |
4678 properties: { | 4695 properties: { |
4679 alt: NP.filterProp(String, String), | 4696 alt: NP.filterProp(String, String), |
4680 height: NP.filterProp(Number, Number), | 4697 height: NP.filterProp(Number, Number), |
4681 src: NP.filter(false, String, true, identity), | 4698 src: NP.filter(false, String, true, identity), |
4682 width: NP.filterProp(Number, Number) | 4699 width: NP.filterProp(Number, Number) |
4683 } | 4700 } |
4684 }); | 4701 }); |
4685 var featureTestImage = makeDOMAccessible(document.createElement('img')); | 4702 var featureTestImage = makeDOMAccessible(document.createElement('img')); |
4686 if ("naturalWidth" in featureTestImage) { | 4703 if ("naturalWidth" in featureTestImage) { |
4687 definePropertiesAwesomely(TameImageElement, { | 4704 definePropertiesAwesomely(TameImageElement, { |
4688 naturalHeight: NP.filterProp(Number, Number), | 4705 naturalHeight: NP.filterProp(Number, Number), |
4689 naturalWidth: NP.filterProp(Number, Number) | 4706 naturalWidth: NP.filterProp(Number, Number) |
4690 }); | 4707 }); |
4691 } | 4708 } |
4692 if ("complete" in featureTestImage) { | 4709 if ("complete" in featureTestImage) { |
4693 definePropertiesAwesomely(TameImageElement, { | 4710 definePropertiesAwesomely(TameImageElement, { |
4694 complete: NP.filterProp(Boolean, Boolean) | 4711 complete: NP.filterProp(Boolean, Boolean) |
4695 }); | 4712 }); |
4696 } | 4713 } |
4697 | 4714 |
4698 function toInt(x) { return x | 0; } | 4715 function toInt(x) { return x | 0; } |
4699 // TODO(kpreid): The conflation of these elements is partly nonsense. | 4716 var TameFormField = defineElement({ |
4700 // Split it into the appropriate narrow interfaces for each element. | 4717 properties: { |
| 4718 disabled: NP.rw, |
| 4719 form: NP.related, |
| 4720 maxLength: NP.rw, |
| 4721 name: NP.rw, |
| 4722 value: NP.filter( |
| 4723 false, function (x) { return x == null ? null : String(x); }, |
| 4724 false, function (x) { return x == null ? '' : '' + x; }) |
| 4725 } |
| 4726 }); |
| 4727 ······ |
4701 var TameInputElement = defineElement({ | 4728 var TameInputElement = defineElement({ |
4702 names: ['select', 'button', 'textarea', 'input'], | 4729 superclass: TameFormField, |
4703 domClass: 'HTMLInputElement', | 4730 domClass: 'HTMLInputElement', |
4704 properties: { | 4731 properties: { |
4705 checked: NP.filterProp(identity, Boolean), | 4732 checked: NP.filterProp(identity, Boolean), |
4706 defaultChecked: NP.rw, | 4733 defaultChecked: NP.rw, |
4707 value: NP.filter( | |
4708 false, function (x) { return x == null ? null : String(x); }, | |
4709 false, function (x) { return x == null ? '' : '' + x; }), | |
4710 defaultValue: NP.filter( | 4734 defaultValue: NP.filter( |
4711 false, function (x) { return x == null ? null : String(x); }, | 4735 false, function (x) { return x == null ? null : String(x); }, |
4712 false, function (x) { return x == null ? '' : '' + x; }), | 4736 false, function (x) { return x == null ? '' : '' + x; }), |
4713 form: NP.related, | |
4714 disabled: NP.rw, | |
4715 readOnly: NP.rw, | 4737 readOnly: NP.rw, |
| 4738 selectedIndex: NP.filterProp(identity, toInt), |
| 4739 size: NP.rw, |
| 4740 type: NP.rw |
| 4741 } |
| 4742 }); |
| 4743 TameInputElement.prototype.select = nodeMethod(function () { |
| 4744 np(this).feral.select(); |
| 4745 }); |
| 4746 |
| 4747 defineElement({ |
| 4748 superclass: TameFormField, |
| 4749 domClass: 'HTMLButtonElement', |
| 4750 properties: { |
| 4751 type: NP.rw |
| 4752 } |
| 4753 }); |
| 4754 |
| 4755 defineElement({ |
| 4756 superclass: TameFormField, |
| 4757 domClass: 'HTMLSelectElement', |
| 4758 properties: { |
| 4759 multiple: NP.rw, |
4716 options: { | 4760 options: { |
4717 enumerable: true, | 4761 enumerable: true, |
4718 get: nodeMethod(function () { | 4762 get: nodeMethod(function () { |
4719 return new TameOptionsList( | 4763 return new TameOptionsList( |
4720 np(this).feral.options, defaultTameNode, 'name'); | 4764 np(this).feral.options, defaultTameNode, 'name'); |
4721 }) | 4765 }) |
4722 }, | 4766 }, |
4723 selectedIndex: NP.filterProp(identity, toInt), | 4767 selectedIndex: NP.filterProp(identity, toInt), |
4724 name: NP.rw, | 4768 type: NP.ro |
4725 accessKey: NP.rw, | |
4726 tabIndex: NP.rw, | |
4727 maxLength: NP.rw, | |
4728 size: NP.rw, | |
4729 type: NP.rw, | |
4730 multiple: NP.rw, | |
4731 cols: NP.rw, | |
4732 rows: NP.rw | |
4733 } | 4769 } |
4734 }); | 4770 }); |
4735 TameInputElement.prototype.select = nodeMethod(function () { | |
4736 np(this).feral.select(); | |
4737 }); | |
4738 | 4771 |
4739 defineElement({ | 4772 defineElement({ |
4740 names: ['label'], | 4773 superclass: TameFormField, |
| 4774 domClass: 'HTMLTextAreaElement', |
| 4775 properties: { |
| 4776 type: NP.rw |
| 4777 } |
| 4778 }); |
| 4779 |
| 4780 defineElement({ |
4741 domClass: 'HTMLLabelElement', | 4781 domClass: 'HTMLLabelElement', |
4742 properties: { | 4782 properties: { |
4743 htmlFor: NP.Rename("for", NP.filterAttr(identity, identity)) | 4783 htmlFor: NP.Rename("for", NP.filterAttr(identity, identity)) |
4744 } | 4784 } |
4745 }); | 4785 }); |
4746 | 4786 |
4747 defineElement({ | 4787 defineElement({ |
4748 names: ['option'], | |
4749 domClass: 'HTMLOptionElement', | 4788 domClass: 'HTMLOptionElement', |
4750 properties: { | 4789 properties: { |
4751 defaultSelected: NP.filterProp(Boolean, Boolean), | 4790 defaultSelected: NP.filterProp(Boolean, Boolean), |
4752 disabled: NP.filterProp(Boolean, Boolean), | 4791 disabled: NP.filterProp(Boolean, Boolean), |
4753 form: NP.related, | 4792 form: NP.related, |
4754 index: NP.filterProp(Number), | 4793 index: NP.filterProp(Number), |
4755 label: NP.filterProp(String, String), | 4794 label: NP.filterProp(String, String), |
4756 selected: NP.filterProp(Boolean, Boolean), | 4795 selected: NP.filterProp(Boolean, Boolean), |
4757 text: NP.filterProp(String, String), | 4796 text: NP.filterProp(String, String), |
4758 // TODO(kpreid): Justify these specialized filters. | 4797 // TODO(kpreid): Justify these specialized filters. |
4759 value: NP.filterProp( | 4798 value: NP.filterProp( |
4760 function (x) { return x == null ? null : String(x); }, | 4799 function (x) { return x == null ? null : String(x); }, |
4761 function (x) { return x == null ? '' : '' + x; }) | 4800 function (x) { return x == null ? '' : '' + x; }) |
4762 } | 4801 } |
4763 }); | 4802 }); |
| 4803 ······ |
| 4804 defineTrivialElement('HTMLParagraphElement'); |
| 4805 defineTrivialElement('HTMLPreElement'); |
4764 | 4806 |
4765 function dynamicCodeDispatchMaker(privates) { | 4807 function dynamicCodeDispatchMaker(privates) { |
4766 window.cajaDynamicScriptCounter = | 4808 window.cajaDynamicScriptCounter = |
4767 window.cajaDynamicScriptCounter ? | 4809 window.cajaDynamicScriptCounter ? |
4768 window.cajaDynamicScriptCounter + 1 : 0; | 4810 window.cajaDynamicScriptCounter + 1 : 0; |
4769 var name = "caja_dynamic_script" + | 4811 var name = "caja_dynamic_script" + |
4770 window.cajaDynamicScriptCounter + '___'; | 4812 window.cajaDynamicScriptCounter + '___'; |
4771 window[name] = function() { | 4813 window[name] = function() { |
4772 try { | 4814 try { |
4773 if (privates.src && | 4815 if (privates.src && |
4774 'function' === typeof domicile.evaluateUntrustedExternalScript) { | 4816 'function' === typeof domicile.evaluateUntrustedExternalScript) { |
4775 domicile.evaluateUntrustedExternalScript(privates.src); | 4817 domicile.evaluateUntrustedExternalScript(privates.src); |
4776 } | 4818 } |
4777 } finally { | 4819 } finally { |
4778 window[name] = undefined; | 4820 window[name] = undefined; |
4779 } | 4821 } |
4780 }; | 4822 }; |
4781 return name + "();"; | 4823 return name + "();"; |
4782 } | 4824 } |
4783 | 4825 |
4784 var TameScriptElement = defineElement({ | 4826 var TameScriptElement = defineElement({ |
4785 names: ['script'], | |
4786 domClass: 'HTMLScriptElement', | 4827 domClass: 'HTMLScriptElement', |
4787 forceChildrenNotEditable: true, | 4828 forceChildrenNotEditable: true, |
4788 properties: { | 4829 properties: { |
4789 src: NP.filter(false, identity, true, identity) | 4830 src: NP.filter(false, identity, true, identity) |
4790 }, | 4831 }, |
4791 construct: function () { | 4832 construct: function () { |
4792 var privates = np(this); | 4833 var privates = np(this); |
4793 privates.feral.appendChild( | 4834 privates.feral.appendChild( |
4794 document.createTextNode( | 4835 document.createTextNode( |
4795 dynamicCodeDispatchMaker(privates))); | 4836 dynamicCodeDispatchMaker(privates))); |
4796 } | 4837 } |
4797 }); | 4838 }); |
4798 | 4839 |
4799 setOwn(TameScriptElement.prototype, 'setAttribute', nodeMethod( | 4840 setOwn(TameScriptElement.prototype, 'setAttribute', nodeMethod( |
4800 function (attrib, value) { | 4841 function (attrib, value) { |
4801 var feral = np(this).feral; | 4842 var feral = np(this).feral; |
4802 np(this).policy.requireEditable(); | 4843 np(this).policy.requireEditable(); |
4803 TameElement.prototype.setAttribute.call(this, attrib, value); | 4844 TameElement.prototype.setAttribute.call(this, attrib, value); |
4804 var attribName = String(attrib).toLowerCase(); | 4845 var attribName = String(attrib).toLowerCase(); |
4805 if ("src" === attribName) { | 4846 if ("src" === attribName) { |
4806 np(this).src = String(value); | 4847 np(this).src = String(value); |
4807 } | 4848 } |
4808 })); | 4849 })); |
4809 | 4850 |
4810 var TameTableCompElement = defineElement({ | 4851 defineTrivialElement('HTMLSpanElement'); |
4811 names: ['td', 'thead', 'tfoot', 'tbody', 'th'], | 4852 |
| 4853 defineElement({ |
| 4854 domClass: 'HTMLTableColElement', |
| 4855 properties: { |
| 4856 align: NP.filterProp(identity, identity), |
| 4857 vAlign: NP.filterProp(identity, identity) |
| 4858 } |
| 4859 }); |
| 4860 ······ |
| 4861 defineTrivialElement('HTMLTableCaptionElement'); |
| 4862 ······ |
| 4863 var TameTableCellElement = defineElement({ |
| 4864 domClass: 'HTMLTableCellElement', |
4812 properties: { | 4865 properties: { |
4813 colSpan: NP.filterProp(identity, identity), | 4866 colSpan: NP.filterProp(identity, identity), |
| 4867 rowSpan: NP.filterProp(identity, identity), |
| 4868 cellIndex: NP.ro, |
| 4869 noWrap: NP.filterProp(identity, identity) // HTML5 Obsolete |
| 4870 } |
| 4871 }); |
| 4872 defineElement({ |
| 4873 superclass: TameTableCellElement, |
| 4874 domClass: 'HTMLTableDataCellElement' |
| 4875 }); |
| 4876 defineElement({ |
| 4877 superclass: TameTableCellElement, |
| 4878 domClass: 'HTMLTableHeaderCellElement' |
| 4879 }); |
| 4880 |
| 4881 function requireIntIn(idx, min, max) { |
| 4882 if (idx !== (idx | 0) || idx < min || idx > max) { |
| 4883 throw new Error(INDEX_SIZE_ERROR); |
| 4884 } |
| 4885 } |
| 4886 |
| 4887 var TameTableRowElement = defineElement({ |
| 4888 domClass: 'HTMLTableRowElement', |
| 4889 properties: { |
4814 cells: { | 4890 cells: { |
4815 // TODO(kpreid): It would be most pleasing to find a way to generali
ze | 4891 // TODO(kpreid): It would be most pleasing to find a way to generali
ze |
4816 // all the accessors which are of the form | 4892 // all the accessors which are of the form |
4817 // return new TameNodeList(np(this).feral...., ..., ...) | 4893 // return new TameNodeList(np(this).feral...., ..., ...) |
4818 enumerable: true, | 4894 enumerable: true, |
4819 get: nodeMethod(function () { | 4895 get: nodeMethod(function () { |
4820 return new TameNodeList(np(this).feral.cells, defaultTameNode); | 4896 return new TameNodeList(np(this).feral.cells, defaultTameNode); |
4821 }) | 4897 }) |
4822 }, | 4898 }, |
4823 cellIndex: NP.ro, | |
4824 rowSpan: NP.filterProp(identity, identity), | |
4825 rows: { | |
4826 enumerable: true, | |
4827 get: nodeMethod(function () { | |
4828 return new TameNodeList(np(this).feral.rows, defaultTameNode); | |
4829 }) | |
4830 }, | |
4831 rowIndex: NP.ro, | 4899 rowIndex: NP.ro, |
4832 sectionRowIndex: NP.ro, | 4900 sectionRowIndex: NP.ro |
4833 align: NP.filterProp(identity, identity), | |
4834 vAlign: NP.filterProp(identity, identity), | |
4835 nowrap: NP.filterProp(identity, identity) | |
4836 } | 4901 } |
4837 }); | 4902 }); |
4838 TameTableCompElement.prototype.insertRow = nodeMethod(function (index) { | |
4839 np(this).policy.requireEditable(); | |
4840 requireIntIn(index, -1, np(this).feral.rows.length); | |
4841 return defaultTameNode(np(this).feral.insertRow(index)); | |
4842 }); | |
4843 TameTableCompElement.prototype.deleteRow = nodeMethod(function (index) { | |
4844 np(this).policy.requireEditable(); | |
4845 requireIntIn(index, -1, np(this).feral.rows.length); | |
4846 np(this).feral.deleteRow(index); | |
4847 }); | |
4848 | |
4849 function requireIntIn(idx, min, max) { | |
4850 if (idx !== (idx | 0) || idx < min || idx > max) { | |
4851 throw new Error(INDEX_SIZE_ERROR); | |
4852 } | |
4853 } | |
4854 | |
4855 var TameTableRowElement = defineElement({ | |
4856 superclass: TameTableCompElement, | |
4857 names: ['tr'], | |
4858 domClass: 'HTMLTableRowElement' | |
4859 }); | |
4860 TameTableRowElement.prototype.insertCell = nodeMethod(function (index) { | 4903 TameTableRowElement.prototype.insertCell = nodeMethod(function (index) { |
4861 // TODO(kpreid): Should this not be a childrenEditable test? | |
4862 np(this).policy.requireEditable(); | 4904 np(this).policy.requireEditable(); |
4863 requireIntIn(index, -1, np(this).feral.cells.length); | 4905 requireIntIn(index, -1, np(this).feral.cells.length); |
4864 return defaultTameNode(np(this).feral.insertCell(index)); | 4906 return defaultTameNode( |
| 4907 np(this).feral.insertCell(index), |
| 4908 np(this).editable); |
4865 }); | 4909 }); |
4866 TameTableRowElement.prototype.deleteCell = nodeMethod(function (index) { | 4910 TameTableRowElement.prototype.deleteCell = nodeMethod(function (index) { |
4867 np(this).policy.requireEditable(); | 4911 np(this).policy.requireEditable(); |
4868 requireIntIn(index, -1, np(this).feral.cells.length); | 4912 requireIntIn(index, -1, np(this).feral.cells.length); |
4869 np(this).feral.deleteCell(index); | 4913 np(this).feral.deleteCell(index); |
4870 }); | 4914 }); |
4871 | 4915 |
| 4916 var TameTableSectionElement = defineElement({ |
| 4917 domClass: 'HTMLTableSectionElement', |
| 4918 properties: { |
| 4919 rows: { |
| 4920 enumerable: true, |
| 4921 get: nodeMethod(function () { |
| 4922 return new TameNodeList(np(this).feral.rows, defaultTameNode); |
| 4923 }) |
| 4924 } |
| 4925 } |
| 4926 }); |
| 4927 TameTableSectionElement.prototype.insertRow = nodeMethod(function(index) { |
| 4928 np(this).policy.requireEditable(); |
| 4929 requireIntIn(index, -1, np(this).feral.rows.length); |
| 4930 return defaultTameNode(np(this).feral.insertRow(index)); |
| 4931 }); |
| 4932 TameTableSectionElement.prototype.deleteRow = nodeMethod(function(index) { |
| 4933 np(this).policy.requireEditable(); |
| 4934 requireIntIn(index, -1, np(this).feral.rows.length); |
| 4935 np(this).feral.deleteRow(index); |
| 4936 }); |
| 4937 |
4872 var TameTableElement = defineElement({ | 4938 var TameTableElement = defineElement({ |
4873 superclass: TameTableCompElement, | 4939 superclass: TameTableSectionElement, // nonstandard but sound |
4874 names: ['table'], | |
4875 domClass: 'HTMLTableElement', | 4940 domClass: 'HTMLTableElement', |
4876 properties: { | 4941 properties: { |
4877 tBodies: { | 4942 tBodies: { |
4878 enumerable: true, | 4943 enumerable: true, |
4879 get: nodeMethod(function () { | 4944 get: nodeMethod(function () { |
4880 if (np(this).policy.childrenVisible) { | 4945 if (np(this).policy.childrenVisible) { |
4881 return new TameNodeList(np(this).feral.tBodies, | 4946 return new TameNodeList(np(this).feral.tBodies, |
4882 defaultTameNode); | 4947 defaultTameNode); |
4883 } else { | 4948 } else { |
4884 return fakeNodeList([]); | 4949 return fakeNodeList([]); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4921 requireIntIn(index, -1, np(this).feral.rows.length); | 4986 requireIntIn(index, -1, np(this).feral.rows.length); |
4922 return defaultTameNode(np(this).feral.insertRow(index)); | 4987 return defaultTameNode(np(this).feral.insertRow(index)); |
4923 }); | 4988 }); |
4924 TameTableElement.prototype.deleteRow = nodeMethod(function (index) { | 4989 TameTableElement.prototype.deleteRow = nodeMethod(function (index) { |
4925 np(this).policy.requireEditable(); | 4990 np(this).policy.requireEditable(); |
4926 requireIntIn(index, -1, np(this).feral.rows.length); | 4991 requireIntIn(index, -1, np(this).feral.rows.length); |
4927 np(this).feral.deleteRow(index); | 4992 np(this).feral.deleteRow(index); |
4928 }); | 4993 }); |
4929 | 4994 |
4930 defineElement({ | 4995 defineElement({ |
4931 names: ['title'], | |
4932 virtualized: true, | 4996 virtualized: true, |
4933 domClass: 'HTMLTitleElement' | 4997 domClass: 'HTMLTitleElement' |
4934 }); | 4998 }); |
| 4999 ······ |
| 5000 defineTrivialElement('HTMLUListElement'); |
4935 | 5001 |
| 5002 defineElement({ |
| 5003 virtualized: null, |
| 5004 domClass: 'HTMLUnknownElement' |
| 5005 }); |
| 5006 ······ |
4936 traceStartup('DT: done with specific elements'); | 5007 traceStartup('DT: done with specific elements'); |
4937 | 5008 |
4938 // Oddball constructors. There are only two of these and we implement | 5009 // Oddball constructors. There are only two of these and we implement |
4939 // both. (Caveat: In actual browsers, new Image().constructor == Image | 5010 // both. (Caveat: In actual browsers, new Image().constructor == Image |
4940 // != HTMLImageElement. We don't implement that.) | 5011 // != HTMLImageElement. We don't implement that.) |
4941 ······ | 5012 ······ |
4942 // Per https://developer.mozilla.org/en-US/docs/DOM/Image as of 2012-09-24 | 5013 // Per https://developer.mozilla.org/en-US/docs/DOM/Image as of 2012-09-24 |
4943 function TameImageFun(width, height) { | 5014 function TameImageFun(width, height) { |
4944 var element = tameDocument.createElement('img'); | 5015 var element = tameDocument.createElement('img'); |
4945 if (width !== undefined) { element.width = width; } | 5016 if (width !== undefined) { element.width = width; } |
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5473 TameStyleConf.p(this).editable = editable; | 5544 TameStyleConf.p(this).editable = editable; |
5474 TameStyleConf.p(this).tameElement = tameEl; | 5545 TameStyleConf.p(this).tameElement = tameEl; |
5475 | 5546 |
5476 TameStyleConf.p(this).readByCanonicalName = function(canonName) { | 5547 TameStyleConf.p(this).readByCanonicalName = function(canonName) { |
5477 return String(style[canonName] || ''); | 5548 return String(style[canonName] || ''); |
5478 }; | 5549 }; |
5479 TameStyleConf.p(this).writeByCanonicalName = function(canonName, val)
{ | 5550 TameStyleConf.p(this).writeByCanonicalName = function(canonName, val)
{ |
5480 style[canonName] = val; | 5551 style[canonName] = val; |
5481 }; | 5552 }; |
5482 }; | 5553 }; |
5483 inertCtor(TameStyle, Object, 'Style'); | 5554 inertCtor(TameStyle, Object /*, 'Style'*/); |
| 5555 // cannot export lazily |
5484 TameStyle.prototype.getPropertyValue = | 5556 TameStyle.prototype.getPropertyValue = |
5485 cajaVM.def(function (cssPropertyName) { | 5557 cajaVM.def(function (cssPropertyName) { |
5486 cssPropertyName = String(cssPropertyName || '').toLowerCase(); | 5558 cssPropertyName = String(cssPropertyName || '').toLowerCase(); |
5487 if (!allowProperty(cssPropertyName)) { return ''; } | 5559 if (!allowProperty(cssPropertyName)) { return ''; } |
5488 var canonName = allCssProperties.getCanonicalPropFromCss( | 5560 var canonName = allCssProperties.getCanonicalPropFromCss( |
5489 cssPropertyName); | 5561 cssPropertyName); |
5490 return TameStyleConf.p(this).readByCanonicalName(canonName); | 5562 return TameStyleConf.p(this).readByCanonicalName(canonName); |
5491 }); | 5563 }); |
5492 setOwn(TameStyle.prototype, "toString", cajaVM.def(function () { | 5564 setOwn(TameStyle.prototype, "toString", cajaVM.def(function () { |
5493 return '[domado object Style]'; | 5565 return '[domado object Style]'; |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5708 // bitmask of trace points | 5780 // bitmask of trace points |
5709 // 0x0001 plugin_dispatchEvent | 5781 // 0x0001 plugin_dispatchEvent |
5710 domicile.domitaTrace = 0; | 5782 domicile.domitaTrace = 0; |
5711 domicile.getDomitaTrace = cajaVM.def( | 5783 domicile.getDomitaTrace = cajaVM.def( |
5712 function () { return domicile.domitaTrace; } | 5784 function () { return domicile.domitaTrace; } |
5713 ); | 5785 ); |
5714 domicile.setDomitaTrace = cajaVM.def( | 5786 domicile.setDomitaTrace = cajaVM.def( |
5715 function (x) { domicile.domitaTrace = x; } | 5787 function (x) { domicile.domitaTrace = x; } |
5716 ); | 5788 ); |
5717 | 5789 |
| 5790 // Freeze exported classes. Must occur before TameHTMLDocument is |
| 5791 // instantiated. |
| 5792 for (var name in nodeClasses) { |
| 5793 var ctor = nodeClasses[name]; |
| 5794 cajaVM.def(ctor); // and its prototype |
| 5795 } |
| 5796 Object.freeze(nodeClasses); |
| 5797 // fail hard if late-added item wouldn't be frozen |
| 5798 |
5718 // Location object -- used by Document and Window and so must be created | 5799 // Location object -- used by Document and Window and so must be created |
5719 // before each. | 5800 // before each. |
5720 function TameLocation() { | 5801 function TameLocation() { |
5721 // TODO(mikesamuel): figure out a mechanism by which the container can | 5802 // TODO(mikesamuel): figure out a mechanism by which the container can |
5722 // specify the gadget's apparent URL. | 5803 // specify the gadget's apparent URL. |
5723 // See http://www.whatwg.org/specs/web-apps/current-work/multipage/histo
ry.html#location0 | 5804 // See http://www.whatwg.org/specs/web-apps/current-work/multipage/histo
ry.html#location0 |
5724 var tameLocation = this; | 5805 var tameLocation = this; |
5725 function defineLocationField(f, dflt) { | 5806 function defineLocationField(f, dflt) { |
5726 Object.defineProperty(tameLocation, f, { | 5807 Object.defineProperty(tameLocation, f, { |
5727 configurable: false, | 5808 configurable: false, |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6000 Object.freeze(tameDefaultView); | 6081 Object.freeze(tameDefaultView); |
6001 | 6082 |
6002 if (np(tameDocument).policy.editable) { | 6083 if (np(tameDocument).policy.editable) { |
6003 tameDocument.defaultView = tameDefaultView; | 6084 tameDocument.defaultView = tameDefaultView; |
6004 | 6085 |
6005 // Hook for document.write support. | 6086 // Hook for document.write support. |
6006 domicile.sanitizeAttrs = sanitizeAttrs; | 6087 domicile.sanitizeAttrs = sanitizeAttrs; |
6007 } | 6088 } |
6008 | 6089 |
6009 // Iterate over all node classes, assigning them to the Window object | 6090 // Iterate over all node classes, assigning them to the Window object |
6010 // under their DOM Level 2 standard name. Also freeze. | 6091 // under their DOM Level 2 standard name. They have been frozen above. |
6011 for (var name in nodeClasses) { | 6092 for (var name in nodeClasses) { |
6012 var ctor = nodeClasses[name]; | 6093 var ctor = nodeClasses[name]; |
6013 cajaVM.def(ctor); // and its prototype | |
6014 cajaVM.def(ctor.prototype); | |
6015 Object.defineProperty(tameWindow, name, { | 6094 Object.defineProperty(tameWindow, name, { |
6016 enumerable: true, | 6095 enumerable: true, |
6017 configurable: true, | 6096 configurable: true, |
6018 writable: true, | 6097 writable: true, |
6019 value: ctor | 6098 value: ctor |
6020 }); | 6099 }); |
6021 } | 6100 } |
6022 | 6101 |
6023 // TODO(ihab.awad): Build a more sophisticated virtual class hierarchy by | 6102 // TODO(ihab.awad): Build a more sophisticated virtual class hierarchy by |
6024 // creating a table of actual subclasses and instantiating tame nodes by | 6103 // having a table of subclass relationships and implementing them. |
6025 // table lookups. This will allow the client code to see a truly consisten
t | |
6026 // DOM class hierarchy. | |
6027 | 6104 |
6028 // This is a list of all HTML-specific element node classes defined by | |
6029 // DOM Level 2 HTML, <http://www.w3.org/TR/DOM-Level-2-HTML/html.html>. | |
6030 // If a node class name in this list is not defined using defineElement or | 6105 // If a node class name in this list is not defined using defineElement or |
6031 // inertCtor above, then it will now be bound to the HTMLElement class. | 6106 // inertCtor above, then it will now be bound to the HTMLElement class. |
6032 var allDomNodeClasses = [ | 6107 var allDomNodeClasses = htmlSchema.getAllKnownScriptInterfaces(); |
6033 'HTMLAnchorElement', | |
6034 'HTMLAppletElement', | |
6035 'HTMLAreaElement', | |
6036 'HTMLBaseElement', | |
6037 'HTMLBaseFontElement', | |
6038 'HTMLBodyElement', | |
6039 'HTMLBRElement', | |
6040 'HTMLButtonElement', | |
6041 'HTMLDirectoryElement', | |
6042 'HTMLDivElement', | |
6043 'HTMLDListElement', | |
6044 'HTMLFieldSetElement', | |
6045 'HTMLFontElement', | |
6046 'HTMLFormElement', | |
6047 'HTMLFrameElement', | |
6048 'HTMLFrameSetElement', | |
6049 'HTMLHeadElement', | |
6050 'HTMLHeadingElement', | |
6051 'HTMLHRElement', | |
6052 'HTMLHtmlElement', | |
6053 'HTMLIFrameElement', | |
6054 'HTMLImageElement', | |
6055 'HTMLInputElement', | |
6056 'HTMLIsIndexElement', | |
6057 'HTMLLabelElement', | |
6058 'HTMLLegendElement', | |
6059 'HTMLLIElement', | |
6060 'HTMLLinkElement', | |
6061 'HTMLMapElement', | |
6062 'HTMLMenuElement', | |
6063 'HTMLMetaElement', | |
6064 'HTMLModElement', | |
6065 'HTMLNavElement', | |
6066 'HTMLObjectElement', | |
6067 'HTMLOListElement', | |
6068 'HTMLOptGroupElement', | |
6069 'HTMLOptionElement', | |
6070 'HTMLParagraphElement', | |
6071 'HTMLParamElement', | |
6072 'HTMLPreElement', | |
6073 'HTMLQuoteElement', | |
6074 'HTMLScriptElement', | |
6075 'HTMLSelectElement', | |
6076 'HTMLStyleElement', | |
6077 'HTMLTableCaptionElement', | |
6078 'HTMLTableCellElement', | |
6079 'HTMLTableColElement', | |
6080 'HTMLTableElement', | |
6081 'HTMLTableRowElement', | |
6082 'HTMLTableSectionElement', | |
6083 'HTMLTextAreaElement', | |
6084 'HTMLTitleElement', | |
6085 'HTMLUListElement' | |
6086 ]; | |
6087 | |
6088 var defaultNodeClassCtor = nodeClasses.HTMLElement; | 6108 var defaultNodeClassCtor = nodeClasses.HTMLElement; |
6089 for (var i = 0; i < allDomNodeClasses.length; i++) { | 6109 for (var i = 0; i < allDomNodeClasses.length; i++) { |
6090 var className = allDomNodeClasses[+i]; | 6110 var className = allDomNodeClasses[+i]; |
6091 if (!(className in tameWindow)) { | 6111 if (!(className in tameWindow)) { |
6092 Object.defineProperty(tameWindow, className, { | 6112 Object.defineProperty(tameWindow, className, { |
6093 enumerable: true, | 6113 enumerable: true, |
6094 configurable: true, | 6114 configurable: true, |
6095 writable: true, | 6115 writable: true, |
6096 value: defaultNodeClassCtor | 6116 value: defaultNodeClassCtor |
6097 }); | 6117 }); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6245 plugin_dispatchToHandler: plugin_dispatchToHandler, | 6265 plugin_dispatchToHandler: plugin_dispatchToHandler, |
6246 getDomicileForWindow: windowToDomicile.get.bind(windowToDomicile) | 6266 getDomicileForWindow: windowToDomicile.get.bind(windowToDomicile) |
6247 }); | 6267 }); |
6248 }); | 6268 }); |
6249 })(); | 6269 })(); |
6250 | 6270 |
6251 // Exports for closure compiler. | 6271 // Exports for closure compiler. |
6252 if (typeof window !== 'undefined') { | 6272 if (typeof window !== 'undefined') { |
6253 window['Domado'] = Domado; | 6273 window['Domado'] = Domado; |
6254 } | 6274 } |
OLD | NEW |