Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 2ee74fd

Browse filesBrowse files
committed
push changes
1 parent 552e0bc commit 2ee74fd
Copy full SHA for 2ee74fd

File tree

45 files changed

+1365
-556
lines changed
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner

45 files changed

+1365
-556
lines changed

‎packages/core/data/observable/index.ts

Copy file name to clipboardExpand all lines: packages/core/data/observable/index.ts
+30-9Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,13 @@ interface EventDescriptior extends AddEventListenerOptions {
9696
removed?: boolean;
9797
abortHandler?: () => void;
9898
thisArg?: unknown;
99-
listener: EventListenerOrEventListenerObject;
99+
listener?: EventListener;
100+
listenerObject?: EventListenerObject;
100101
}
101102

102103
function isThisArg(value: any) {
103104
if (!value) return false;
105+
if (typeof value === 'function') return false;
104106
if (typeof value !== 'object') return false;
105107
if (value?.constructor?.toString().indexOf('class') === 0) return true;
106108
// If object has none of the values in event options, it's thisArg.
@@ -111,12 +113,22 @@ function isThisArg(value: any) {
111113
}
112114

113115
const getEventDescriptor = (target: EventTarget, type: string, listener: EventListenerOrEventListenerObject, options?: (AddEventListenerOptions & { thisArg: any }) | boolean): EventDescriptior => {
114-
const handleEvent = typeof listener === 'function' ? listener : listener.handleEvent;
116+
const listenerPart: { listener?: EventListener; listenerObject?: EventListenerObject } = {};
117+
118+
if (typeof listener === 'function') {
119+
listenerPart.listener = listener;
120+
} else if (listener.handleEvent) {
121+
listenerPart.listenerObject = listener;
122+
if (typeof options === 'function') {
123+
listenerPart.listener = options;
124+
}
125+
}
126+
115127
/**
116128
* the most common case is handled first. No options. No capturing. No thisArg.
117129
*/
118130
if (!options || typeof options === 'boolean') {
119-
return { target, capture: !!options, type, listener: handleEvent };
131+
return { target, capture: !!options, type, ...listenerPart };
120132
}
121133

122134
// The second most common case, last argument is thisArg.
@@ -125,7 +137,7 @@ const getEventDescriptor = (target: EventTarget, type: string, listener: EventLi
125137
type,
126138
target,
127139
thisArg: options,
128-
listener: handleEvent,
140+
...listenerPart,
129141
};
130142
}
131143
// Finally the last and "new" case of event options.
@@ -137,8 +149,8 @@ const getEventDescriptor = (target: EventTarget, type: string, listener: EventLi
137149
once,
138150
passive,
139151
signal,
140-
listener: handleEvent,
141152
thisArg: thisArg,
153+
...listenerPart,
142154
};
143155
};
144156

@@ -593,11 +605,20 @@ export class Observable extends EventTarget implements globalThis.EventTarget {
593605
}
594606

595607
let returnValue;
596-
if (thisArg) {
597-
returnValue = (listener as EventListener).apply(thisArg, [event]);
598-
} else {
599-
returnValue = (listener as EventListener)(event as NativeDOMEvent);
608+
if (descriptor.listenerObject) {
609+
if (thisArg) {
610+
returnValue = descriptor.listenerObject.handleEvent.apply(thisArg, [event]);
611+
} else {
612+
returnValue = descriptor.listenerObject.handleEvent(event as NativeDOMEvent);
613+
}
614+
} else if (listener) {
615+
if (thisArg) {
616+
returnValue = listener.apply(thisArg, [event]);
617+
} else {
618+
returnValue = listener(event as NativeDOMEvent);
619+
}
600620
}
621+
601622
// This ensures errors thrown inside asynchronous functions do not get swallowed
602623
if (returnValue && returnValue instanceof Promise) {
603624
returnValue.catch((err) => {

‎packages/core/package.json

Copy file name to clipboardExpand all lines: packages/core/package.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@nativescript/core",
3-
"version": "8.4.8",
3+
"version": "8.4.8-dom-alpha.0",
44
"description": "A JavaScript library providing an easy to use api for interacting with iOS and Android platform APIs.",
55
"main": "index",
66
"types": "index.d.ts",
+79Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { addTaggedAdditionalCSS, removeTaggedAdditionalCSS } from '../../../../styling/style-scope';
2+
3+
class CSSRuleList extends Array {}
4+
5+
class CSSRule {
6+
constructor(public cssText: string) {}
7+
}
8+
9+
export class CSSStyleSheet {
10+
timestampTag: number;
11+
cssRules: CSSRuleList;
12+
ownerRule: CSSRule;
13+
get rules(): CSSRuleList {
14+
return this.cssRules;
15+
}
16+
addRule(selector?: string, style?: string, index?: number): number {
17+
return this.insertRule(`${selector} {${style}}`, index);
18+
}
19+
deleteRule(index: number): void {
20+
this.removeRule(index);
21+
}
22+
insertRule(rule: string, index?: number): number {
23+
if (typeof index !== 'number') index = -1;
24+
this.cssRules.splice(index, 0, new CSSRule(rule));
25+
return 0;
26+
}
27+
removeRule(index?: number): void {
28+
this.cssRules.splice(index, 1);
29+
}
30+
replace(text: string): Promise<CSSStyleSheet> {
31+
return new Promise((resolve) => {
32+
this.replaceSync(text);
33+
resolve(this);
34+
});
35+
}
36+
replaceSync(text: string): void {
37+
this.cssRules = [new CSSRule(text)];
38+
this.adoptStyles();
39+
}
40+
disabled: boolean;
41+
href: string;
42+
media: MediaList;
43+
ownerNode: globalThis.Element | ProcessingInstruction;
44+
parentStyleSheet: CSSStyleSheet;
45+
title: string;
46+
type: string;
47+
48+
adoptStyles() {
49+
this.timestampTag = this.timestampTag || Date.now();
50+
const cssText = (this.cssRules as unknown as Array<CSSRule>).map((rule) => rule.cssText).join('');
51+
removeTaggedAdditionalCSS(this.timestampTag);
52+
addTaggedAdditionalCSS(cssText, this.timestampTag);
53+
}
54+
55+
// Todo
56+
// Parse the ast
57+
// prefix with element tag so it becomes scoped.
58+
// private parseCSSAst() {
59+
// const cssText = (this.cssRules as unknown as Array<CSSRule>).map((rule) => rule.cssText).join('');
60+
// let ast;
61+
// if (cssText) {
62+
// if (__CSS_PARSER__ === 'css-tree') {
63+
// const cssTreeParse = require('../../../../../css/css-tree-parser').cssTreeParse;
64+
// ast = cssTreeParse(cssText);
65+
// } else if (__CSS_PARSER__ === 'nativescript') {
66+
// const CSS3Parser = require('../../../../../css/CSS3Parser').CSS3Parser;
67+
// const CSSNativeScript = require('../../../../../css/CSSNativeScript').CSSNativeScript;
68+
// const cssparser = new CSS3Parser(cssText);
69+
// const stylesheet = cssparser.parseAStylesheet();
70+
// const cssNS = new CSSNativeScript();
71+
// ast = cssNS.parseStylesheet(stylesheet);
72+
// } else if (__CSS_PARSER__ === 'rework') {
73+
// const parseCss = require('../../../../../css').parse;
74+
// ast = parseCss(cssText, { source: undefined });
75+
// }
76+
// }
77+
// return ast;
78+
// }
79+
}

‎packages/core/ui/core/dom/src/custom-element/CustomElementRegistry.ts

Copy file name to clipboardExpand all lines: packages/core/ui/core/dom/src/custom-element/CustomElementRegistry.ts
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ export default class CustomElementRegistry {
3131
elementClass._observedAttributes = elementClass.observedAttributes;
3232
}
3333

34+
//@ts-ignore Add a css type so this tag name can be referred to in css files.
35+
elementClass.prototype.cssType = tagName;
36+
3437
if (this._callbacks[tagName]) {
3538
const callbacks = this._callbacks[tagName];
3639
delete this._callbacks[tagName];

‎packages/core/ui/core/dom/src/dom-implementation/DOMImplementation.ts

Copy file name to clipboardExpand all lines: packages/core/ui/core/dom/src/dom-implementation/DOMImplementation.ts
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ export default class DOMImplementation {
2626
// @ts-ignore
2727
documentClass._defaultView = this._ownerDocument.defaultView;
2828
// @ts-ignore
29-
return new documentClass();
29+
const doc = new documentClass();
30+
doc.initDocument();
31+
return doc;
3032
}
3133

3234
/**
+29-8Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import type Element from '../element/Element';
12
import Node from '../node/Node';
3+
import NodeTypeEnum from '../node/NodeTypeEnum';
24

35
/**
46
* Character data base class.
@@ -8,31 +10,50 @@ import Node from '../node/Node';
810
*/
911
export default abstract class CharacterData extends Node {
1012
get data(): string {
11-
return this.data;
13+
return this._nodeValue;
1214
}
1315

1416
set data(data) {
15-
this.data = data;
17+
this._nodeValue = data;
18+
propogateTextChangeToParentElement(this);
1619
}
1720
get length() {
18-
return this.data.length;
21+
return this._nodeValue.length;
1922
}
2023

2124
get nodeValue() {
22-
return this.data;
25+
return this._nodeValue;
2326
}
2427
set nodeValue(data) {
25-
this.data = data;
28+
this._nodeValue = data;
29+
propogateTextChangeToParentElement(this);
2630
}
2731

2832
get textContent() {
29-
return this.data;
33+
return this._nodeValue;
3034
}
3135
set textContent(text) {
32-
this.data = `${text}`;
36+
this._nodeValue = `${text}`;
37+
propogateTextChangeToParentElement(this);
3338
}
3439

3540
appendData(data: string) {
36-
this.data += data;
41+
this._nodeValue += data;
42+
}
43+
}
44+
45+
function propogateTextChangeToParentElement(node: Node) {
46+
let parentElement: Element = null;
47+
let currentNode = node.parentNode;
48+
while (currentNode && !parentElement) {
49+
if (currentNode.nodeType === NodeTypeEnum.elementNode) {
50+
parentElement = currentNode as Element;
51+
}
52+
currentNode = currentNode.parentNode;
53+
}
54+
if (!parentElement) return;
55+
56+
if ('text' in parentElement) {
57+
parentElement['text'] = parentElement.textContent;
3758
}
3859
}

‎packages/core/ui/core/dom/src/nodes/comment/Comment.ts

Copy file name to clipboardExpand all lines: packages/core/ui/core/dom/src/nodes/comment/Comment.ts
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Node from '../node/Node';
22
import CharacterData from '../character-data/CharacterData';
3+
import type Element from '../element/Element';
34

45
/**
56
* Comment node.

‎packages/core/ui/core/dom/src/nodes/document-fragment/DocumentFragment.ts

Copy file name to clipboardExpand all lines: packages/core/ui/core/dom/src/nodes/document-fragment/DocumentFragment.ts
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ export default class DocumentFragment extends ParentNode {
77
public nodeType = NodeTypeEnum.documentFragmentNode;
88
public nodeName: string = '#document-fragment';
99
public localName: string = '#document-fragment';
10+
isParentNode = true;
1011
constructor() {
1112
super();
1213
this._rootNode = this;
1314
}
1415
}
16+
DocumentFragment.prototype['adoptedStyleSheets'] = [];

‎packages/core/ui/core/dom/src/nodes/document-type/DocumentType.ts

Copy file name to clipboardExpand all lines: packages/core/ui/core/dom/src/nodes/document-type/DocumentType.ts
-3Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ export default class DocumentType extends Node {
99
public publicId = '';
1010
public systemId = '';
1111

12-
set parentNode(node: any) {
13-
this._parentNode = node;
14-
}
1512
//@ts-ignore
1613
get nodeName() {
1714
return this.name;

‎packages/core/ui/core/dom/src/nodes/document/Document.ts

Copy file name to clipboardExpand all lines: packages/core/ui/core/dom/src/nodes/document/Document.ts
+37-3Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import ElementTag from '../../config/ElementTag';
22
import DOMImplementation from '../../dom-implementation/DOMImplementation';
33
import { Event } from '../../event/Event';
4+
import INodeFilter from '../../tree-walker/INodeFilter';
5+
import TreeWalker from '../../tree-walker/TreeWalker';
46
import Comment from '../comment/Comment';
57
import DocumentFragment from '../document-fragment/DocumentFragment';
68
import HTMLElement from '../html-element/HTMLElement';
9+
import type Node from '../node/Node';
710
import NodeTypeEnum from '../node/NodeTypeEnum';
811
import ParentNode from '../parent-node/ParentNode';
912
import Text from '../text/Text';
@@ -12,16 +15,18 @@ const createElement = (type: string, owner: Document) => {
1215
let element;
1316

1417
if (htmlElementRegistry.has(type)) {
15-
element = new (htmlElementRegistry.get(type) as any)();
16-
element.tagName = htmlElementRegistry[type].NODE_TAG_NAME;
18+
const Class = htmlElementRegistry.get(type) as any;
19+
element = new Class();
20+
element.tagName = Class.NODE_TAG_NAME;
1721
} else if (ElementTag[type]) {
1822
element = new ElementTag[type]();
1923
element.tagName = type;
2024
} else if (customElements.get(type)) {
2125
element = new (customElements.get(type))();
2226
element.tagName = type;
2327
} else {
24-
element = new HTMLElement(NodeTypeEnum.elementNode, type);
28+
element = new HTMLElement();
29+
element.tagName = type;
2530
}
2631
element.ownerDocument = owner;
2732
element._isRegisteredDOMElement = true;
@@ -38,6 +43,7 @@ export default class Document extends ParentNode {
3843
body: HTMLElement;
3944
implementation: DOMImplementation;
4045
nodeType: NodeTypeEnum = NodeTypeEnum.documentNode;
46+
isParentNode = true;
4147
/* eslint-disable class-methods-use-this */
4248
constructor() {
4349
super();
@@ -100,4 +106,32 @@ export default class Document extends ParentNode {
100106
set defaultView(scope: any) {
101107
this._defaultView = scope;
102108
}
109+
110+
/**
111+
* Creates a Tree Walker.
112+
*
113+
* @param root Root.
114+
* @param [whatToShow] What to show.
115+
* @param [filter] Filter.
116+
*/
117+
public createTreeWalker(root: Node, whatToShow = -1, filter: INodeFilter = null): TreeWalker {
118+
return new TreeWalker(root, whatToShow, filter);
119+
}
120+
121+
/**
122+
* Imports a node.
123+
*
124+
* @param node Node to import.
125+
* @param [deep=false] Set to "true" if the clone should be deep.
126+
*/
127+
public importNode(node: Node, deep = false): Node {
128+
if (!node.isNode) {
129+
throw new Error('Parameter 1 was not of type Node.');
130+
}
131+
const clone = node.cloneNode(deep);
132+
(<Document>clone.ownerDocument) = this;
133+
return clone;
134+
}
103135
}
136+
137+
Document.prototype['adoptedStyleSheets'] = [];

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.