Merge pull request #11188 from michalzielanski/late-obj-init
Late object initialization
This commit is contained in:
@@ -128,7 +128,9 @@ class Feature extends BaseObject {
|
||||
* @api
|
||||
*/
|
||||
clone() {
|
||||
const clone = new Feature(this.getProperties());
|
||||
const clone = new Feature(
|
||||
this.hasProperties() ? this.getProperties() : null
|
||||
);
|
||||
clone.setGeometryName(this.getGeometryName());
|
||||
const geometry = this.getGeometry();
|
||||
if (geometry) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import Event from './events/Event.js';
|
||||
import ObjectEventType from './ObjectEventType.js';
|
||||
import Observable from './Observable.js';
|
||||
import {assign} from './obj.js';
|
||||
import {assign, isEmpty} from './obj.js';
|
||||
import {getUid} from './util.js';
|
||||
|
||||
/**
|
||||
@@ -95,9 +95,9 @@ class BaseObject extends Observable {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object<string, *>}
|
||||
* @type {Object<string, *>}
|
||||
*/
|
||||
this.values_ = {};
|
||||
this.values_ = null;
|
||||
|
||||
if (opt_values !== undefined) {
|
||||
this.setProperties(opt_values);
|
||||
@@ -112,7 +112,7 @@ class BaseObject extends Observable {
|
||||
*/
|
||||
get(key) {
|
||||
let value;
|
||||
if (this.values_.hasOwnProperty(key)) {
|
||||
if (this.values_ && this.values_.hasOwnProperty(key)) {
|
||||
value = this.values_[key];
|
||||
}
|
||||
return value;
|
||||
@@ -124,7 +124,7 @@ class BaseObject extends Observable {
|
||||
* @api
|
||||
*/
|
||||
getKeys() {
|
||||
return Object.keys(this.values_);
|
||||
return (this.values_ && Object.keys(this.values_)) || [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,7 +133,14 @@ class BaseObject extends Observable {
|
||||
* @api
|
||||
*/
|
||||
getProperties() {
|
||||
return assign({}, this.values_);
|
||||
return (this.values_ && assign({}, this.values_)) || {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {boolean} The object has properties.
|
||||
*/
|
||||
hasProperties() {
|
||||
return !!this.values_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,11 +163,12 @@ class BaseObject extends Observable {
|
||||
* @api
|
||||
*/
|
||||
set(key, value, opt_silent) {
|
||||
const values = this.values_ || (this.values_ = {});
|
||||
if (opt_silent) {
|
||||
this.values_[key] = value;
|
||||
values[key] = value;
|
||||
} else {
|
||||
const oldValue = this.values_[key];
|
||||
this.values_[key] = value;
|
||||
const oldValue = values[key];
|
||||
values[key] = value;
|
||||
if (oldValue !== value) {
|
||||
this.notify(key, oldValue);
|
||||
}
|
||||
@@ -187,9 +195,12 @@ class BaseObject extends Observable {
|
||||
* @api
|
||||
*/
|
||||
unset(key, opt_silent) {
|
||||
if (key in this.values_) {
|
||||
if (this.values_ && key in this.values_) {
|
||||
const oldValue = this.values_[key];
|
||||
delete this.values_[key];
|
||||
if (isEmpty(this.values_)) {
|
||||
this.values_ = null;
|
||||
}
|
||||
if (!opt_silent) {
|
||||
this.notify(key, oldValue);
|
||||
}
|
||||
|
||||
@@ -40,21 +40,21 @@ class Target extends Disposable {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object<string, number>}
|
||||
* @type {Object<string, number>}
|
||||
*/
|
||||
this.pendingRemovals_ = {};
|
||||
this.pendingRemovals_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object<string, number>}
|
||||
* @type {Object<string, number>}
|
||||
*/
|
||||
this.dispatching_ = {};
|
||||
this.dispatching_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object<string, Array<import("../events.js").Listener>>}
|
||||
* @type {Object<string, Array<import("../events.js").Listener>>}
|
||||
*/
|
||||
this.listeners_ = {};
|
||||
this.listeners_ = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,13 +65,10 @@ class Target extends Disposable {
|
||||
if (!type || !listener) {
|
||||
return;
|
||||
}
|
||||
let listeners = this.listeners_[type];
|
||||
if (!listeners) {
|
||||
listeners = [];
|
||||
this.listeners_[type] = listeners;
|
||||
}
|
||||
if (listeners.indexOf(listener) === -1) {
|
||||
listeners.push(listener);
|
||||
const listeners = this.listeners_ || (this.listeners_ = {});
|
||||
const listenersForType = listeners[type] || (listeners[type] = []);
|
||||
if (listenersForType.indexOf(listener) === -1) {
|
||||
listenersForType.push(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,14 +89,17 @@ class Target extends Disposable {
|
||||
if (!evt.target) {
|
||||
evt.target = this.eventTarget_ || this;
|
||||
}
|
||||
const listeners = this.listeners_[type];
|
||||
const listeners = this.listeners_ && this.listeners_[type];
|
||||
let propagate;
|
||||
if (listeners) {
|
||||
if (!(type in this.dispatching_)) {
|
||||
this.dispatching_[type] = 0;
|
||||
this.pendingRemovals_[type] = 0;
|
||||
const dispatching = this.dispatching_ || (this.dispatching_ = {});
|
||||
const pendingRemovals =
|
||||
this.pendingRemovals_ || (this.pendingRemovals_ = {});
|
||||
if (!(type in dispatching)) {
|
||||
dispatching[type] = 0;
|
||||
pendingRemovals[type] = 0;
|
||||
}
|
||||
++this.dispatching_[type];
|
||||
++dispatching[type];
|
||||
for (let i = 0, ii = listeners.length; i < ii; ++i) {
|
||||
if ('handleEvent' in listeners[i]) {
|
||||
propagate = /** @type {import("../events.js").ListenerObject} */ (listeners[
|
||||
@@ -115,14 +115,14 @@ class Target extends Disposable {
|
||||
break;
|
||||
}
|
||||
}
|
||||
--this.dispatching_[type];
|
||||
if (this.dispatching_[type] === 0) {
|
||||
let pendingRemovals = this.pendingRemovals_[type];
|
||||
delete this.pendingRemovals_[type];
|
||||
while (pendingRemovals--) {
|
||||
--dispatching[type];
|
||||
if (dispatching[type] === 0) {
|
||||
let pr = pendingRemovals[type];
|
||||
delete pendingRemovals[type];
|
||||
while (pr--) {
|
||||
this.removeEventListener(type, VOID);
|
||||
}
|
||||
delete this.dispatching_[type];
|
||||
delete dispatching[type];
|
||||
}
|
||||
return propagate;
|
||||
}
|
||||
@@ -132,7 +132,7 @@ class Target extends Disposable {
|
||||
* Clean up.
|
||||
*/
|
||||
disposeInternal() {
|
||||
clear(this.listeners_);
|
||||
this.listeners_ && clear(this.listeners_);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,10 +140,10 @@ class Target extends Disposable {
|
||||
* order that they will be called in.
|
||||
*
|
||||
* @param {string} type Type.
|
||||
* @return {Array<import("../events.js").Listener>} Listeners.
|
||||
* @return {Array<import("../events.js").Listener>|undefined} Listeners.
|
||||
*/
|
||||
getListeners(type) {
|
||||
return this.listeners_[type];
|
||||
return (this.listeners_ && this.listeners_[type]) || undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,6 +152,9 @@ class Target extends Disposable {
|
||||
* @return {boolean} Has listeners.
|
||||
*/
|
||||
hasListener(opt_type) {
|
||||
if (!this.listeners_) {
|
||||
return false;
|
||||
}
|
||||
return opt_type
|
||||
? opt_type in this.listeners_
|
||||
: Object.keys(this.listeners_).length > 0;
|
||||
@@ -162,11 +165,11 @@ class Target extends Disposable {
|
||||
* @param {import("../events.js").Listener} listener Listener.
|
||||
*/
|
||||
removeEventListener(type, listener) {
|
||||
const listeners = this.listeners_[type];
|
||||
const listeners = this.listeners_ && this.listeners_[type];
|
||||
if (listeners) {
|
||||
const index = listeners.indexOf(listener);
|
||||
if (index !== -1) {
|
||||
if (type in this.pendingRemovals_) {
|
||||
if (this.pendingRemovals_ && type in this.pendingRemovals_) {
|
||||
// make listener a no-op, and remove later in #dispatchEvent()
|
||||
listeners[index] = VOID;
|
||||
++this.pendingRemovals_[type];
|
||||
|
||||
@@ -199,6 +199,11 @@ class EsriJSON extends JSONFeature {
|
||||
writeFeatureObject(feature, opt_options) {
|
||||
opt_options = this.adaptOptions(opt_options);
|
||||
const object = {};
|
||||
if (!feature.hasProperties()) {
|
||||
object['attributes'] = {};
|
||||
return object;
|
||||
}
|
||||
const properties = feature.getProperties();
|
||||
const geometry = feature.getGeometry();
|
||||
if (geometry) {
|
||||
object['geometry'] = writeGeometry(geometry, opt_options);
|
||||
@@ -214,9 +219,8 @@ class EsriJSON extends JSONFeature {
|
||||
),
|
||||
});
|
||||
}
|
||||
delete properties[feature.getGeometryName()];
|
||||
}
|
||||
const properties = feature.getProperties();
|
||||
delete properties[feature.getGeometryName()];
|
||||
if (!isEmpty(properties)) {
|
||||
object['attributes'] = properties;
|
||||
} else {
|
||||
|
||||
@@ -212,29 +212,32 @@ class GML2 extends GMLBase {
|
||||
context.serializers = {};
|
||||
context.serializers[featureNS] = {};
|
||||
}
|
||||
const properties = feature.getProperties();
|
||||
const keys = [];
|
||||
const values = [];
|
||||
for (const key in properties) {
|
||||
const value = properties[key];
|
||||
if (value !== null) {
|
||||
keys.push(key);
|
||||
values.push(value);
|
||||
if (
|
||||
key == geometryName ||
|
||||
typeof (/** @type {?} */ (value).getSimplifiedGeometry) === 'function'
|
||||
) {
|
||||
if (!(key in context.serializers[featureNS])) {
|
||||
context.serializers[featureNS][key] = makeChildAppender(
|
||||
this.writeGeometryElement,
|
||||
this
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (!(key in context.serializers[featureNS])) {
|
||||
context.serializers[featureNS][key] = makeChildAppender(
|
||||
writeStringTextNode
|
||||
);
|
||||
if (feature.hasProperties()) {
|
||||
const properties = feature.getProperties();
|
||||
for (const key in properties) {
|
||||
const value = properties[key];
|
||||
if (value !== null) {
|
||||
keys.push(key);
|
||||
values.push(value);
|
||||
if (
|
||||
key == geometryName ||
|
||||
typeof (/** @type {?} */ (value).getSimplifiedGeometry) ===
|
||||
'function'
|
||||
) {
|
||||
if (!(key in context.serializers[featureNS])) {
|
||||
context.serializers[featureNS][key] = makeChildAppender(
|
||||
this.writeGeometryElement,
|
||||
this
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (!(key in context.serializers[featureNS])) {
|
||||
context.serializers[featureNS][key] = makeChildAppender(
|
||||
writeStringTextNode
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -843,29 +843,32 @@ class GML3 extends GMLBase {
|
||||
context.serializers = {};
|
||||
context.serializers[featureNS] = {};
|
||||
}
|
||||
const properties = feature.getProperties();
|
||||
const keys = [];
|
||||
const values = [];
|
||||
for (const key in properties) {
|
||||
const value = properties[key];
|
||||
if (value !== null) {
|
||||
keys.push(key);
|
||||
values.push(value);
|
||||
if (
|
||||
key == geometryName ||
|
||||
typeof (/** @type {?} */ (value).getSimplifiedGeometry) === 'function'
|
||||
) {
|
||||
if (!(key in context.serializers[featureNS])) {
|
||||
context.serializers[featureNS][key] = makeChildAppender(
|
||||
this.writeGeometryElement,
|
||||
this
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (!(key in context.serializers[featureNS])) {
|
||||
context.serializers[featureNS][key] = makeChildAppender(
|
||||
writeStringTextNode
|
||||
);
|
||||
if (feature.hasProperties()) {
|
||||
const properties = feature.getProperties();
|
||||
for (const key in properties) {
|
||||
const value = properties[key];
|
||||
if (value !== null) {
|
||||
keys.push(key);
|
||||
values.push(value);
|
||||
if (
|
||||
key == geometryName ||
|
||||
typeof (/** @type {?} */ (value).getSimplifiedGeometry) ===
|
||||
'function'
|
||||
) {
|
||||
if (!(key in context.serializers[featureNS])) {
|
||||
context.serializers[featureNS][key] = makeChildAppender(
|
||||
this.writeGeometryElement,
|
||||
this
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (!(key in context.serializers[featureNS])) {
|
||||
context.serializers[featureNS][key] = makeChildAppender(
|
||||
writeStringTextNode
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,16 +207,22 @@ class GeoJSON extends JSONFeature {
|
||||
object.id = id;
|
||||
}
|
||||
|
||||
const geometry = feature.getGeometry();
|
||||
if (geometry) {
|
||||
object.geometry = writeGeometry(geometry, opt_options);
|
||||
if (!feature.hasProperties()) {
|
||||
return object;
|
||||
}
|
||||
|
||||
const properties = feature.getProperties();
|
||||
delete properties[feature.getGeometryName()];
|
||||
const geometry = feature.getGeometry();
|
||||
if (geometry) {
|
||||
object.geometry = writeGeometry(geometry, opt_options);
|
||||
|
||||
delete properties[feature.getGeometryName()];
|
||||
}
|
||||
|
||||
if (!isEmpty(properties)) {
|
||||
object.properties = properties;
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user