如何为此 class 定义 Google Closure Compiler externs
How to define the Google Closure Compiler externs for this class
我有以下 JavaScript class 定义,它可以正常工作并且我使用 Google Closure Compiler 编译:
class State {
constructor(x, y, z, rotationX, rotationY) {
this.x = x;
this.y = y;
this.z = z;
this.rotationX = rotationX;
this.rotationY = rotationY;
}
set matrix(value) {
// Magic
}
get matrix() {
// More magic
}
set red(value) {
this.setAttribute(attributeRed, value)
}
get red() {
return this.getAttribute(attributeRed);;
}
static fromUrlSearchParams(searchParams) {
return new State(parseInt (searchParams.get("x"), 10),
parseInt (searchParams.get("y"), 10),
parseInt (searchParams.get("z"), 10),
parseFloat(searchParams.get("rotationX")),
parseFloat(searchParams.get("rotationY")));
}
toUrlSearchParams() {
let searchParams = new URLSearchParams();
searchParams.set("x", this.red);
searchParams.set("y", this.green);
searchParams.set("z", this.blue);
searchParams.set("rotationX", this.pitch);
searchParams.set("rotationY", this.yaw);
return searchParams;
}
}
此类型是我代码的 public 接口的一部分,这意味着我必须防止 Closure 编译器重命名其符号。我正在编写一个使用 --externs
开关传递给 Closure 编译器的外部文件。这是我目前所拥有的:
State = class {
/**
* @constructor
* @param {number} x
* @param {number} y
* @param {number} z
* @param {number} rotationX
* @param {number} rotationY
*/
constructor(x, y, z, rotationX, rotationY) {
/** @type {number} */
this.x = x;
/** @type {number} */
this.y = y;
/** @type {number} */
this.z = z;
/** @type {number} */
this.rotationX = rotationX;
/** @type {number} */
this.rotationY = rotationY;
}
// Insert property export here. If you just knew how...
/** @return {State} */
static fromUrlSearchParams(searchParams) {}
/** @return {URLSearchParams} */
toUrlSearchParams() {}
};
我在完成外部文件时遇到了三个问题:
- 构造函数的参数(
x
、y
、z
、rotationX
、rotationY
)已重命名。我需要做什么来防止这种情况发生?
static
方法fromUrlSearchParams(searchParams)
被编译器移除,因为它得出的结论是死代码,因为它在编译后的代码内部没有使用。如何导出 static
方法?
- 如何将
matrix
属性 标记为 public 界面的一部分?
编辑:
在花了 几个 小时解决这个问题后,阅读了我能找到的所有文档,在 GitHub 上抓取文件,测试各种在线外部生成器并获得副本《Closure - The Definitive Guide》一书的问题仍然没有解决。
经过十多年的发展,Closure Compiler 文档除了最基本的示例之外,对于其他所有内容仍然毫无用处。你一定是在开玩笑吧。
这是我到目前为止尝试过的:
class State {
/**
* @constructor
* @param {number} x
* @param {number} y
* @param {number} z
* @param {number} rotationX
* @param {number} rotationY
*/
constructor(x, y, z, rotationX, rotationY) {
/** @type {number} */
this.x = x;
/** @type {number} */
this.y = y;
/** @type {number} */
this.z = z;
/** @type {number} */
this.rotationX = rotationX;
/** @type {number} */
this.rotationY = rotationY;
}
/**
* @nocollapse
* @param {URLSearchParams} searchParams
* @return {State}
*/
static fromUrlSearchParams(searchParams) {}
/** @return {URLSearchParams} */
toUrlSearchParams() {}
};
与原始文件的区别在于使用 class State {
而不是 State = class {
。有趣的是,这会导致以下错误消息:
ERROR - [JSC_BLOCK_SCOPED_DECL_MULTIPLY_DECLARED_ERROR] Duplicate let / const / class / function declaration in the same scope is not allowed.
不知道为什么会有所不同,但无论如何,让我们继续前进。下一次尝试:
/**
* @constructor
* @param {number} x
* @param {number} y
* @param {number} z
* @param {number} rotationX
* @param {number} rotationX
*/
var State = {};
/** @type {number} */
State.prototype.x;
/** @type {number} */
State.prototype.y;
/** @type {number} */
State.prototype.z;
/** @type {number} */
State.prototype.rotationX;
/** @type {number} */
State.prototype.rotationX;
/**
* @nocollapse
* @param {URLSearchParams} searchParams
* @return {State}
*/
State.fromUrlSearchParams = function(searchParams) {};
/** @return {URLSearchParams} */
State.prototype.toUrlSearchParams = function() {};
运行 它与该代码的结果是
ERROR - [JSC_VAR_MULTIPLY_DECLARED_ERROR] Variable ColorCubeState declared more than once. First occurrence: blabla.js
class State {
^^^^^
好吧,我们再来一次。如果我传递一个源文件和一个外部文件,为什么编译器会声明它已经定义,这对我来说是个谜。一个定义它,另一个注释它,或者你会这么想。
任何尝试都无法避免静态方法被编译器删除。
除了用我的代码构建和调试编译器之外,我看不出还有什么可以尝试的。幸运的是,这个问题有保证的解决方案:简单地不使用 Google Closure 编译器。
我不是这方面的专家,但这里有一些可以尝试的方法。也可以看看
https://github.com/google/closure-compiler/wiki/JS-Modules
您可以尝试在文件末尾添加
出口 = 州。
您可能还需要在顶部添加:
goog.module('State');
为什么要防止构造函数的参数被重命名?这些在构造函数之外是不可见的,所以应该不是问题。
试试这个:
goog.exportSymbol('fromUrlSearchParams', fromUrlSearchParams);
编译器可能不支持 - JavaScript getter 和 setter 属性。看到这个
https://google.github.io/styleguide/jsguide.html#features-classes-getters-and-setters
以下有效:
输入文件:
"use strict";
const attributeX = "x";
const attributeY = "y";
const attributeZ = "z";
const attributeRotationX = "rotationX"
const attributeRotationY = "rotationY";
/** @implements {StateInterface} */
globalThis["State"] = class {
constructor(x, y, z, rotationX, rotationY) {
this.x = x;
this.y = y;
this.z = z;
this.rotationX = rotationX;
this.rotationY = rotationY;
}
/**
* @nocollapse
* @suppress {checkTypes}
*/
static "fromUrlSearchParams"(searchParams) {
return new globalThis["State"](parseInt (searchParams.get(attributeX), 10),
parseInt (searchParams.get(attributeY), 10),
parseInt (searchParams.get(attributeZ), 10),
parseFloat(searchParams.get(attributeRotationX)),
parseFloat(searchParams.get(attributeRotationY)));
}
toUrlSearchParams() {
let searchParams = new URLSearchParams();
searchParams.set(attributeX , this.x .toString(10));
searchParams.set(attributeY , this.y .toString(10));
searchParams.set(attributeZ , this.z .toString(10));
searchParams.set(attributeRotationX, this.rotationX.toString(10));
searchParams.set(attributeRotationY, this.rotationY.toString(10));
return searchParams;
}
}
外部文件:
/**
* @fileoverview
* @externs
*/
/** @interface */
class StateInterface {
/**
* @param {number} x
* @param {number} y
* @param {number} z
* @param {number} rotationX
* @param {number} rotationY
*/
constructor(x, y, z, rotationX, rotationY) {
/** @type {number} */
this.x = x;
/** @type {number} */
this.y = y;
/** @type {number} */
this.z = z;
/** @type {number} */
this.rotationX = rotationX;
/** @type {number} */
this.rotationY = rotationY;
}
/**
* @param {URLSearchParams} searchParams
* @return {StateInterface}
*/
static fromUrlSearchParams(searchParams) {}
/** @return {URLSearchParams} */
toUrlSearchParams() {}
};
我有以下 JavaScript class 定义,它可以正常工作并且我使用 Google Closure Compiler 编译:
class State {
constructor(x, y, z, rotationX, rotationY) {
this.x = x;
this.y = y;
this.z = z;
this.rotationX = rotationX;
this.rotationY = rotationY;
}
set matrix(value) {
// Magic
}
get matrix() {
// More magic
}
set red(value) {
this.setAttribute(attributeRed, value)
}
get red() {
return this.getAttribute(attributeRed);;
}
static fromUrlSearchParams(searchParams) {
return new State(parseInt (searchParams.get("x"), 10),
parseInt (searchParams.get("y"), 10),
parseInt (searchParams.get("z"), 10),
parseFloat(searchParams.get("rotationX")),
parseFloat(searchParams.get("rotationY")));
}
toUrlSearchParams() {
let searchParams = new URLSearchParams();
searchParams.set("x", this.red);
searchParams.set("y", this.green);
searchParams.set("z", this.blue);
searchParams.set("rotationX", this.pitch);
searchParams.set("rotationY", this.yaw);
return searchParams;
}
}
此类型是我代码的 public 接口的一部分,这意味着我必须防止 Closure 编译器重命名其符号。我正在编写一个使用 --externs
开关传递给 Closure 编译器的外部文件。这是我目前所拥有的:
State = class {
/**
* @constructor
* @param {number} x
* @param {number} y
* @param {number} z
* @param {number} rotationX
* @param {number} rotationY
*/
constructor(x, y, z, rotationX, rotationY) {
/** @type {number} */
this.x = x;
/** @type {number} */
this.y = y;
/** @type {number} */
this.z = z;
/** @type {number} */
this.rotationX = rotationX;
/** @type {number} */
this.rotationY = rotationY;
}
// Insert property export here. If you just knew how...
/** @return {State} */
static fromUrlSearchParams(searchParams) {}
/** @return {URLSearchParams} */
toUrlSearchParams() {}
};
我在完成外部文件时遇到了三个问题:
- 构造函数的参数(
x
、y
、z
、rotationX
、rotationY
)已重命名。我需要做什么来防止这种情况发生? static
方法fromUrlSearchParams(searchParams)
被编译器移除,因为它得出的结论是死代码,因为它在编译后的代码内部没有使用。如何导出static
方法?- 如何将
matrix
属性 标记为 public 界面的一部分?
编辑:
在花了 几个 小时解决这个问题后,阅读了我能找到的所有文档,在 GitHub 上抓取文件,测试各种在线外部生成器并获得副本《Closure - The Definitive Guide》一书的问题仍然没有解决。
经过十多年的发展,Closure Compiler 文档除了最基本的示例之外,对于其他所有内容仍然毫无用处。你一定是在开玩笑吧。
这是我到目前为止尝试过的:
class State {
/**
* @constructor
* @param {number} x
* @param {number} y
* @param {number} z
* @param {number} rotationX
* @param {number} rotationY
*/
constructor(x, y, z, rotationX, rotationY) {
/** @type {number} */
this.x = x;
/** @type {number} */
this.y = y;
/** @type {number} */
this.z = z;
/** @type {number} */
this.rotationX = rotationX;
/** @type {number} */
this.rotationY = rotationY;
}
/**
* @nocollapse
* @param {URLSearchParams} searchParams
* @return {State}
*/
static fromUrlSearchParams(searchParams) {}
/** @return {URLSearchParams} */
toUrlSearchParams() {}
};
与原始文件的区别在于使用 class State {
而不是 State = class {
。有趣的是,这会导致以下错误消息:
ERROR - [JSC_BLOCK_SCOPED_DECL_MULTIPLY_DECLARED_ERROR] Duplicate let / const / class / function declaration in the same scope is not allowed.
不知道为什么会有所不同,但无论如何,让我们继续前进。下一次尝试:
/**
* @constructor
* @param {number} x
* @param {number} y
* @param {number} z
* @param {number} rotationX
* @param {number} rotationX
*/
var State = {};
/** @type {number} */
State.prototype.x;
/** @type {number} */
State.prototype.y;
/** @type {number} */
State.prototype.z;
/** @type {number} */
State.prototype.rotationX;
/** @type {number} */
State.prototype.rotationX;
/**
* @nocollapse
* @param {URLSearchParams} searchParams
* @return {State}
*/
State.fromUrlSearchParams = function(searchParams) {};
/** @return {URLSearchParams} */
State.prototype.toUrlSearchParams = function() {};
运行 它与该代码的结果是
ERROR - [JSC_VAR_MULTIPLY_DECLARED_ERROR] Variable ColorCubeState declared more than once. First occurrence: blabla.js
class State {
^^^^^
好吧,我们再来一次。如果我传递一个源文件和一个外部文件,为什么编译器会声明它已经定义,这对我来说是个谜。一个定义它,另一个注释它,或者你会这么想。
任何尝试都无法避免静态方法被编译器删除。
除了用我的代码构建和调试编译器之外,我看不出还有什么可以尝试的。幸运的是,这个问题有保证的解决方案:简单地不使用 Google Closure 编译器。
我不是这方面的专家,但这里有一些可以尝试的方法。也可以看看 https://github.com/google/closure-compiler/wiki/JS-Modules
您可以尝试在文件末尾添加
出口 = 州。
您可能还需要在顶部添加:
goog.module('State');
为什么要防止构造函数的参数被重命名?这些在构造函数之外是不可见的,所以应该不是问题。
试试这个:
goog.exportSymbol('fromUrlSearchParams', fromUrlSearchParams);
-
编译器可能不支持
- JavaScript getter 和 setter 属性。看到这个 https://google.github.io/styleguide/jsguide.html#features-classes-getters-and-setters
以下有效:
输入文件:
"use strict";
const attributeX = "x";
const attributeY = "y";
const attributeZ = "z";
const attributeRotationX = "rotationX"
const attributeRotationY = "rotationY";
/** @implements {StateInterface} */
globalThis["State"] = class {
constructor(x, y, z, rotationX, rotationY) {
this.x = x;
this.y = y;
this.z = z;
this.rotationX = rotationX;
this.rotationY = rotationY;
}
/**
* @nocollapse
* @suppress {checkTypes}
*/
static "fromUrlSearchParams"(searchParams) {
return new globalThis["State"](parseInt (searchParams.get(attributeX), 10),
parseInt (searchParams.get(attributeY), 10),
parseInt (searchParams.get(attributeZ), 10),
parseFloat(searchParams.get(attributeRotationX)),
parseFloat(searchParams.get(attributeRotationY)));
}
toUrlSearchParams() {
let searchParams = new URLSearchParams();
searchParams.set(attributeX , this.x .toString(10));
searchParams.set(attributeY , this.y .toString(10));
searchParams.set(attributeZ , this.z .toString(10));
searchParams.set(attributeRotationX, this.rotationX.toString(10));
searchParams.set(attributeRotationY, this.rotationY.toString(10));
return searchParams;
}
}
外部文件:
/**
* @fileoverview
* @externs
*/
/** @interface */
class StateInterface {
/**
* @param {number} x
* @param {number} y
* @param {number} z
* @param {number} rotationX
* @param {number} rotationY
*/
constructor(x, y, z, rotationX, rotationY) {
/** @type {number} */
this.x = x;
/** @type {number} */
this.y = y;
/** @type {number} */
this.z = z;
/** @type {number} */
this.rotationX = rotationX;
/** @type {number} */
this.rotationY = rotationY;
}
/**
* @param {URLSearchParams} searchParams
* @return {StateInterface}
*/
static fromUrlSearchParams(searchParams) {}
/** @return {URLSearchParams} */
toUrlSearchParams() {}
};