Page MenuHomeWildfire Games

Correctly serialize/deserialize user-defined JS objects.
Changes PlannedPublic

Authored by wraitii on May 17 2020, 7:27 PM.

Details

Reviewers
Itms
Trac Tickets
#4698
Summary

User-defined JS objects can be serialised/deserialised properly. This includes Vector2D and Vector3D.

The approach I take is not via serialization into C++ (and thus via EngineScriptsConversions), but by simply re-constructing the object. This works well because basically all of our objects have constructors that take no arguments (all components, Vector2/3 classes). It's more generic than serialising through C++, and would for example likely work well for AI objects or nodder-defined objects.
For objects with constructors that take arguments, the construct call can fail, in which case it reports an error.
Many constructors with arguments would still work, because JS works rather well with undefined values.


This introduces a more elaborate "GetConstructor" function in scriptinterface, which also tries using lexical scope to get closured objects (such as Class definitions). It's a further improvement on rP22487 as that would have failed for Class objects.


Fixes #4698.

Test Plan

Agree with the approach & the implementation.

Event Timeline

wraitii created this revision.May 17 2020, 7:27 PM
wraitii added inline comments.
binaries/data/mods/public/globalscripts/tests/test_vector.js
24

It doesn't work for these, though it works for Vector2D. It does work if I move the definitions to the Vector file. I'm assuming I'm doing something stupid without noticing.

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/vs2015-differential/1627/display/redirect

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/docker-differential/2153/display/redirect

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/macos-differential/739/display/redirect

The lexical scope of how test_vector.js is executed might need to change, I'm not sure. It's possible that it is already fine though. I can take a closer look later.

Meanwhile, I'm not seeing where the logic is for determinig the prototype, tracking it, and then applying it. Where is that logic?

I guess you want to generalise it so that it could for for any class. Right now that logic lives in EngineScriptConversions.cpp, which for a given CPP type (e.g. Vector2D), obtains the related class from JS's global scope by name, and constructs it accordingly.

Generalising that to work for any object would be cool I suppose, but I'm not familiar enough with the code base yet to know how or if that could work well. How would it know what the associated CPP representation should be for an arbitrary JS class? Or maybe we don't need that? (I don't know.)

Can you elaborate on the specific problem we currently have with Vector2D? I assume there is a user-observable issue of some sort, but the Trac issue is too vague for me (I'm not able to translate the code-specific terms to a player scenario, I still have a big knowledge gap between the bits I know from the code and the bits I know from the game).

For example, could you write a test case specific to Vector2D with some code we'd like to make work, but currently doesn't?

wraitii updated this revision to Diff 11947.May 21 2020, 8:29 AM
wraitii retitled this revision from Serialize objects with their prototypes [WIP] to Correctly serialize/deserialize user-defined JS objects. [WIP].
wraitii edited the summary of this revision. (Show Details)

Updated version. This lets us support Serialize/Deserialize (as in components) on any user-defined JS object (including, of course, components).

I've stopped supporting custom non-null Serialize with no Deserialize because the architecture is kind of awkward and it's a fairly niche usage (only Player.js uses it and it's an easy fix on the JS side).

Still TODO:

  • Support DebugSerializer
  • Optimizations. I'm storing prototype names for components which is hardly necessary, and further I have temporarily removed the "has_custom_[de]serialize" code.
  • Update the code in rP22487 (and possibly elsewhere) to use my new GetConstructor function.
  • revert rP21834

It would be nice to have some more tests too.


Also I noticed that we serialise Vector3D in Attack.PerformAttack (for the ranged case), in the Timer. This works for now, but it's dangerous unless this patch gets committed.

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/macos-differential/763/display/redirect

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/vs2015-differential/1651/display/redirect

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/docker-differential/2177/display/redirect

wraitii updated this revision to Diff 11949.May 21 2020, 10:59 AM
wraitii edited the test plan for this revision. (Show Details)

Do the TODOs from the above comments.

I'ce switched the debug serialiser to include both Serialised and "raw" content in case Serialize() is present. This might give us some more data on what goes wrong in rare OOS cases.


I've tested Danubius and a few other maps, saved/loaded games, no obvious problem appeared.
I've also tested with -serializationtest and -rejointest and everything worked properly.
Removing [WIP] tag, this is ready from my end.

Owners added a subscriber: Restricted Owners Package.May 21 2020, 10:59 AM

Successful build - Chance fights ever on the side of the prudent.

Linter detected issues:
Executing section Source...

source/simulation2/scripting/ScriptComponent.h
|   1| /*·Copyright·(C)·2017·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2017"

source/simulation2/scripting/ScriptComponent.h
|  30| class·CComponentTypeScript
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classCComponentTypeScript{' is invalid C code. Use --std or --language to configure the language.

source/simulation2/serialization/IDeserializer.h
|   1| /*·Copyright·(C)·2017·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2017"

source/simulation2/serialization/IDeserializer.h
|  34| class·IDeserializer
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classIDeserializer{' is invalid C code. Use --std or --language to configure the language.

source/simulation2/serialization/ISerializer.cpp
|   1| /*·Copyright·(C)·2011·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2011"

source/scriptinterface/ScriptInterface.cpp
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"

source/simulation2/serialization/BinarySerializer.cpp
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"

source/simulation2/serialization/DebugSerializer.cpp
|   1| /*·Copyright·(C)·2017·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2017"

source/simulation2/components/CCmpAIManager.cpp
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"

source/simulation2/scripting/EngineScriptConversions.cpp
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"

source/simulation2/scripting/EngineScriptConversions.cpp
| 173| »   »   FAIL_VOID("Failed·to·get·Vector3D·constructor");
|    | [MAJOR] CPPCheckBear (unknownMacro):
|    | There is an unknown macro here somewhere. Configuration is required. If STMT is a macro then please configure it.

source/simulation2/tests/test_ComponentManager.h
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"

source/simulation2/tests/test_ComponentManager.h
|  41| class·TestComponentManager·:·public·CxxTest::TestSuite
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classTestComponentManager:' is invalid C code. Use --std or --language to configure the language.

source/simulation2/components/tests/test_scripts.h
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"

source/simulation2/components/tests/test_scripts.h
|  24| class·TestComponentScripts·:·public·CxxTest::TestSuite
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classTestComponentScripts:' is invalid C code. Use --std or --language to configure the language.

source/simulation2/serialization/ISerializer.h
|   1| /*·Copyright·(C)·2011·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2011"

source/simulation2/serialization/ISerializer.h
| 120| class·ISerializer
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classISerializer{' is invalid C code. Use --std or --language to configure the language.

source/simulation2/serialization/StdDeserializer.h
|   1| /*·Copyright·(C)·2017·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2017"

source/simulation2/serialization/StdDeserializer.h
|  34| 
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classIDeserializer{' is invalid C code. Use --std or --language to configure the language.

source/simulation2/scripting/ScriptComponent.cpp
|   1| /*·Copyright·(C)·2017·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2017"

source/simulation2/serialization/BinarySerializer.h
|   1| /*·Copyright·(C)·2017·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2017"

source/simulation2/serialization/BinarySerializer.h
| 120| »   »   m_RawStreamBuf(m_Impl),
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classISerializer{' is invalid C code. Use --std or --language to configure the language.

source/simulation2/serialization/DebugSerializer.h
|   1| /*·Copyright·(C)·2017·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2017"

source/simulation2/serialization/DebugSerializer.h
| 120| The line belonging to the following result cannot be printed because it refers to a line that doesn't seem to exist in the given file.
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classISerializer{' is invalid C code. Use --std or --language to configure the language.

source/simulation2/serialization/StdDeserializer.cpp
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"
Executing section JS...
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'a' found.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|   3|   3| TestScript1_values.prototype.Init = function() {
|   4|   4| 	this.x = +this.template.x;
|   5|   5| 	this.str = "this is a string";
|   6|    |-	this.things = { a: 1, b: "2", c: [3, "4", [5, []]] };
|    |   6|+	this.things = { "a": 1, b: "2", c: [3, "4", [5, []]] };
|   7|   7| };
|   8|   8| 
|   9|   9| TestScript1_values.prototype.GetX = function() {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'b' found.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|   3|   3| TestScript1_values.prototype.Init = function() {
|   4|   4| 	this.x = +this.template.x;
|   5|   5| 	this.str = "this is a string";
|   6|    |-	this.things = { a: 1, b: "2", c: [3, "4", [5, []]] };
|    |   6|+	this.things = { a: 1, "b": "2", c: [3, "4", [5, []]] };
|   7|   7| };
|   8|   8| 
|   9|   9| TestScript1_values.prototype.GetX = function() {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'c' found.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|   3|   3| TestScript1_values.prototype.Init = function() {
|   4|   4| 	this.x = +this.template.x;
|   5|   5| 	this.str = "this is a string";
|   6|    |-	this.things = { a: 1, b: "2", c: [3, "4", [5, []]] };
|    |   6|+	this.things = { a: 1, b: "2", "c": [3, "4", [5, []]] };
|   7|   7| };
|   8|   8| 
|   9|   9| TestScript1_values.prototype.GetX = function() {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'y' found.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  39|  39| 
|  40|  40| TestScript1_nontree.prototype.Init = function() {
|  41|  41| 	var n = [1];
|  42|    |-	this.x = [n, n, null, { y: n }];
|    |  42|+	this.x = [n, n, null, { "y": n }];
|  43|  43| 	this.x[2] = this.x;
|  44|  44| };
|  45|  45| 
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  60|  60| };
|  61|  61| 
|  62|  62| TestScript1_custom.prototype.Serialize = function() {
|  63|    |-	return {c:1};
|    |  63|+	return { c:1};
|  64|  64| };
|  65|  65| 
|  66|  66| TestScript1_custom.prototype.Deserialize = function(data) {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'c' found.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  60|  60| };
|  61|  61| 
|  62|  62| TestScript1_custom.prototype.Serialize = function() {
|  63|    |-	return {c:1};
|    |  63|+	return {"c":1};
|  64|  64| };
|  65|  65| 
|  66|  66| TestScript1_custom.prototype.Deserialize = function(data) {
|    | [NORMAL] ESLintBear (key-spacing):
|    | Missing space before value for key 'c'.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  60|  60| };
|  61|  61| 
|  62|  62| TestScript1_custom.prototype.Serialize = function() {
|  63|    |-	return {c:1};
|    |  63|+	return {c: 1};
|  64|  64| };
|  65|  65| 
|  66|  66| TestScript1_custom.prototype.Deserialize = function(data) {
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  60|  60| };
|  61|  61| 
|  62|  62| TestScript1_custom.prototype.Serialize = function() {
|  63|    |-	return {c:1};
|    |  63|+	return {c:1 };
|  64|  64| };
|  65|  65| 
|  66|  66| TestScript1_custom.prototype.Deserialize = function(data) {
|    | [NORMAL] ESLintBear (space-before-function-paren):
|    | Unexpected space before function parentheses.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  75|  75| 
|  76|  76| TestScript1_getter.prototype.Init = function() {
|  77|  77| 	this.x = 100;
|  78|    |-	this.__defineGetter__('x', function () { print("FAIL\n"); die(); return 200; });
|    |  78|+	this.__defineGetter__('x', function() { print("FAIL\n"); die(); return 200; });
|  79|  79| };
|  80|  80| 
|  81|  81| Engine.RegisterComponentType(IID_Test1, "TestScript1_getter", TestScript1_getter);

binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  24| »   }·catch·(e)·{·}
|    | [NORMAL] ESLintBear (no-empty):
|    | Empty block statement.

binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  28| »   }·catch·(e)·{·}
|    | [NORMAL] ESLintBear (no-empty):
|    | Empty block statement.

binaries/data/mods/public/simulation/components/Player.js
| 352| »   for·(var·type·in·amounts)
|    | [NORMAL] JSHintBear:
|    | 'type' is already defined.
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/maps/random/danubius_triggers.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/maps/random/danubius_triggers.js
| 288| 288| 
| 289| 289| 		let animations = ritualAnimations[
| 290| 290| 			cmpIdentity.HasClass("Healer") ? "healer" :
| 291|    |-			cmpIdentity.HasClass("Female") ? "female" : "male"];
|    | 291|+				cmpIdentity.HasClass("Female") ? "female" : "male"];
| 292| 292| 
| 293| 293| 		let cmpVisual = Engine.QueryInterface(ent, IID_Visual);
| 294| 294| 		if (!cmpVisual)
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/globalscripts/vector.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/globalscripts/vector.js
|   1|    |-/////////////////////////////////////////////////////////////////////
|    |   1|+// ///////////////////////////////////////////////////////////////////
|   2|   2| //	Vector2D
|   3|   3| //
|   4|   4| //	Class for representing and manipulating 2D vectors
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/globalscripts/vector.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/globalscripts/vector.js
|   3|   3| //
|   4|   4| //	Class for representing and manipulating 2D vectors
|   5|   5| //
|   6|    |-/////////////////////////////////////////////////////////////////////
|    |   6|+// ///////////////////////////////////////////////////////////////////
|   7|   7| 
|   8|   8| // TODO: Type errors if v not instanceof Vector classes
|   9|   9| // TODO: Possibly implement in C++
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/globalscripts/vector.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/globalscripts/vector.js
| 253| 253| 	return v1.x * v2.x + v1.y * v2.y;
| 254| 254| };
| 255| 255| 
| 256|    |-/////////////////////////////////////////////////////////////////////
|    | 256|+// ///////////////////////////////////////////////////////////////////
| 257| 257| //	Vector3D
| 258| 258| //
| 259| 259| //	Class for representing and manipulating 3D vectors
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/globalscripts/vector.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/globalscripts/vector.js
| 258| 258| //
| 259| 259| //	Class for representing and manipulating 3D vectors
| 260| 260| //
| 261|    |-/////////////////////////////////////////////////////////////////////
|    | 261|+// ///////////////////////////////////////////////////////////////////
| 262| 262| 
| 263| 263| function Vector3D(x = 0, y = 0, z = 0)
| 264| 264| {
Executing section cli...

Link to build: https://jenkins.wildfiregames.com/job/docker-differential/2180/display/redirect

wraitii updated this revision to Diff 12018.May 25 2020, 11:15 PM
wraitii retitled this revision from Correctly serialize/deserialize user-defined JS objects. [WIP] to Correctly serialize/deserialize user-defined JS objects..
wraitii edited the summary of this revision. (Show Details)

(Actually remove the WIP tag)

This removes the check for "no mandatory arguments". Some cases will still work correctly, and we'll report errors otherwise, so it seems worth not checking again.

Also add some proper tests for this in test_serialize.

Successful build - Chance fights ever on the side of the prudent.

Linter detected issues:
Executing section Source...

source/simulation2/serialization/DebugSerializer.h
|   1| /*·Copyright·(C)·2017·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2017"

source/simulation2/serialization/DebugSerializer.h
| 120| The line belonging to the following result cannot be printed because it refers to a line that doesn't seem to exist in the given file.
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classISerializer{' is invalid C code. Use --std or --language to configure the language.

source/simulation2/serialization/BinarySerializer.h
|   1| /*·Copyright·(C)·2017·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2017"

source/simulation2/serialization/BinarySerializer.h
| 120| »   »   m_RawStreamBuf(m_Impl),
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classISerializer{' is invalid C code. Use --std or --language to configure the language.

source/simulation2/scripting/ScriptComponent.cpp
|   1| /*·Copyright·(C)·2017·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2017"

source/simulation2/serialization/IDeserializer.h
|   1| /*·Copyright·(C)·2017·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2017"

source/simulation2/serialization/IDeserializer.h
|  34| class·IDeserializer
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classIDeserializer{' is invalid C code. Use --std or --language to configure the language.

source/simulation2/tests/test_ComponentManager.h
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"

source/simulation2/tests/test_ComponentManager.h
|  41| class·TestComponentManager·:·public·CxxTest::TestSuite
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classTestComponentManager:' is invalid C code. Use --std or --language to configure the language.

source/simulation2/serialization/DebugSerializer.cpp
|   1| /*·Copyright·(C)·2017·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2017"

source/simulation2/serialization/ISerializer.h
|   1| /*·Copyright·(C)·2011·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2011"

source/simulation2/serialization/ISerializer.h
| 120| class·ISerializer
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classISerializer{' is invalid C code. Use --std or --language to configure the language.

source/simulation2/serialization/StdDeserializer.h
|   1| /*·Copyright·(C)·2017·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2017"

source/simulation2/serialization/StdDeserializer.h
|  34| 
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classIDeserializer{' is invalid C code. Use --std or --language to configure the language.

source/simulation2/serialization/ISerializer.cpp
|   1| /*·Copyright·(C)·2011·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2011"

source/simulation2/tests/test_Serializer.h
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"

source/simulation2/tests/test_Serializer.h
|  47| class·TestSerializer·:·public·CxxTest::TestSuite
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classTestSerializer:' is invalid C code. Use --std or --language to configure the language.

source/simulation2/components/tests/test_scripts.h
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"

source/simulation2/components/tests/test_scripts.h
|  24| class·TestComponentScripts·:·public·CxxTest::TestSuite
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classTestComponentScripts:' is invalid C code. Use --std or --language to configure the language.

source/simulation2/scripting/EngineScriptConversions.cpp
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"

source/simulation2/scripting/EngineScriptConversions.cpp
| 173| »   »   FAIL_VOID("Failed·to·get·Vector3D·constructor");
|    | [MAJOR] CPPCheckBear (unknownMacro):
|    | There is an unknown macro here somewhere. Configuration is required. If STMT is a macro then please configure it.

source/simulation2/serialization/BinarySerializer.cpp
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"

source/simulation2/serialization/StdDeserializer.cpp
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"

source/simulation2/scripting/ScriptComponent.h
|   1| /*·Copyright·(C)·2017·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2017"

source/simulation2/scripting/ScriptComponent.h
|  30| class·CComponentTypeScript
|    | [MAJOR] CPPCheckBear (syntaxError):
|    | Code 'classCComponentTypeScript{' is invalid C code. Use --std or --language to configure the language.

source/scriptinterface/ScriptInterface.cpp
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"

source/simulation2/components/CCmpAIManager.cpp
|   1| /*·Copyright·(C)·2019·Wildfire·Games.
|    | [NORMAL] LicenseYearBear:
|    | License should have "2020" year instead of "2019"
Executing section JS...
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 4 tabs but found 3.
|----|    | /zpool0/trunk/binaries/data/mods/public/maps/random/danubius_triggers.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/maps/random/danubius_triggers.js
| 288| 288| 
| 289| 289| 		let animations = ritualAnimations[
| 290| 290| 			cmpIdentity.HasClass("Healer") ? "healer" :
| 291|    |-			cmpIdentity.HasClass("Female") ? "female" : "male"];
|    | 291|+				cmpIdentity.HasClass("Female") ? "female" : "male"];
| 292| 292| 
| 293| 293| 		let cmpVisual = Engine.QueryInterface(ent, IID_Visual);
| 294| 294| 		if (!cmpVisual)

binaries/data/mods/public/simulation/components/Player.js
| 352| »   for·(var·type·in·amounts)
|    | [NORMAL] JSHintBear:
|    | 'type' is already defined.
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'a' found.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|   3|   3| TestScript1_values.prototype.Init = function() {
|   4|   4| 	this.x = +this.template.x;
|   5|   5| 	this.str = "this is a string";
|   6|    |-	this.things = { a: 1, b: "2", c: [3, "4", [5, []]] };
|    |   6|+	this.things = { "a": 1, b: "2", c: [3, "4", [5, []]] };
|   7|   7| };
|   8|   8| 
|   9|   9| TestScript1_values.prototype.GetX = function() {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'b' found.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|   3|   3| TestScript1_values.prototype.Init = function() {
|   4|   4| 	this.x = +this.template.x;
|   5|   5| 	this.str = "this is a string";
|   6|    |-	this.things = { a: 1, b: "2", c: [3, "4", [5, []]] };
|    |   6|+	this.things = { a: 1, "b": "2", c: [3, "4", [5, []]] };
|   7|   7| };
|   8|   8| 
|   9|   9| TestScript1_values.prototype.GetX = function() {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'c' found.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|   3|   3| TestScript1_values.prototype.Init = function() {
|   4|   4| 	this.x = +this.template.x;
|   5|   5| 	this.str = "this is a string";
|   6|    |-	this.things = { a: 1, b: "2", c: [3, "4", [5, []]] };
|    |   6|+	this.things = { a: 1, b: "2", "c": [3, "4", [5, []]] };
|   7|   7| };
|   8|   8| 
|   9|   9| TestScript1_values.prototype.GetX = function() {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'y' found.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  40|  40| 
|  41|  41| TestScript1_nontree.prototype.Init = function() {
|  42|  42| 	var n = [1];
|  43|    |-	this.x = [n, n, null, { y: n }];
|    |  43|+	this.x = [n, n, null, { "y": n }];
|  44|  44| 	this.x[2] = this.x;
|  45|  45| };
|  46|  46| 
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  61|  61| };
|  62|  62| 
|  63|  63| TestScript1_custom.prototype.Serialize = function() {
|  64|    |-	return {c:1};
|    |  64|+	return { c:1};
|  65|  65| };
|  66|  66| 
|  67|  67| TestScript1_custom.prototype.Deserialize = function(data) {
|    | [NORMAL] ESLintBear (quote-props):
|    | Unquoted property 'c' found.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  61|  61| };
|  62|  62| 
|  63|  63| TestScript1_custom.prototype.Serialize = function() {
|  64|    |-	return {c:1};
|    |  64|+	return {"c":1};
|  65|  65| };
|  66|  66| 
|  67|  67| TestScript1_custom.prototype.Deserialize = function(data) {
|    | [NORMAL] ESLintBear (key-spacing):
|    | Missing space before value for key 'c'.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  61|  61| };
|  62|  62| 
|  63|  63| TestScript1_custom.prototype.Serialize = function() {
|  64|    |-	return {c:1};
|    |  64|+	return {c: 1};
|  65|  65| };
|  66|  66| 
|  67|  67| TestScript1_custom.prototype.Deserialize = function(data) {
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  61|  61| };
|  62|  62| 
|  63|  63| TestScript1_custom.prototype.Serialize = function() {
|  64|    |-	return {c:1};
|    |  64|+	return {c:1 };
|  65|  65| };
|  66|  66| 
|  67|  67| TestScript1_custom.prototype.Deserialize = function(data) {
|    | [NORMAL] ESLintBear (space-before-function-paren):
|    | Unexpected space before function parentheses.
|----|    | /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|    |++++| /zpool0/trunk/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  76|  76| 
|  77|  77| TestScript1_getter.prototype.Init = function() {
|  78|  78| 	this.x = 100;
|  79|    |-	this.__defineGetter__('x', function () { print("FAIL\n"); die(); return 200; });
|    |  79|+	this.__defineGetter__('x', function() { print("FAIL\n"); die(); return 200; });
|  80|  80| };
|  81|  81| 
|  82|  82| Engine.RegisterComponentType(IID_Test1, "TestScript1_getter", TestScript1_getter);

binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  25| »   }·catch·(e)·{·}
|    | [NORMAL] ESLintBear (no-empty):
|    | Empty block statement.

binaries/data/mods/_test.sim/simulation/components/test-serialize.js
|  29| »   }·catch·(e)·{·}
|    | [NORMAL] ESLintBear (no-empty):
|    | Empty block statement.
Executing section cli...

Link to build: https://jenkins.wildfiregames.com/job/docker-differential/2233/display/redirect

Itms added a reviewer: Itms.Fri, Jul 17, 11:09 AM
Itms added a comment.Mon, Jul 20, 2:34 PM

Hi wraitii, while I was looking into those serializable prototypes the other day, I discovered that most of this code is currently dead. I do not know if you noticed, I didn't see this mentioned above.

CCmpAIManager's RegisterSerializablePrototype is used nowhere. As a consequence, the serializer and deserializer do not have any prototype to serialize. This experimental patch: P216 does not change anything. I tested saving and loading single-player games with AIs, with and without the patch, the save stays compatible.

I would like to remove this dead code. @wraitii, if I do so, would this diff still be relevant? If yes, can you tell me what would be its interest or its use case?

In D2746#124987, @Itms wrote:

Hi wraitii, while I was looking into those serializable prototypes the other day, I discovered that most of this code is currently dead. I do not know if you noticed, I didn't see this mentioned above.

I did notice, if you look at the diff I remove the AI prototype code myself for example.

I would like to remove this dead code. @wraitii, if I do so, would this diff still be relevant? If yes, can you tell me what would be its interest or its use case?

Yes. The purpose here is to have code to serialise/deserialize user-created objects (i.e. objects with user-created prototypes), such as the js Vector2D or Vector3D, natively. Currently, if one stores a Vector2D in a component, it generally will OOS when deserializing since it is deserialised as a dict.

As such, I need to some logic to save a prototype's data.

binaries/data/mods/public/maps/scenarios/test.xml
70

These two files shouldn't be here :p

Itms added a comment.Mon, Jul 20, 5:03 PM

Currently, if one stores a Vector2D in a component, it generally will OOS when deserializing since it is deserialised as a dict.

ah that's a damn good reason! 😄 thanks for the answer.

In that case here's what I will do when I'm back on Wednesday: I will update D2881, in which I will change the "script backrefs" to not use an ObjectIdCache anymore. You will be able to do the same for the "serializable prototype" structure here. Once both patches are in, ObjectIdCache can be removed from the codebase and not block the SM upgrade.

In the meantime, can you already make a patch that just removes the dead code from the AI manager component? I'll review and accept it from my phone, so you can commit it.

In D2746#125047, @Itms wrote:

In the meantime, can you already make a patch that just removes the dead code from the AI manager component? I'll review and accept it from my phone, so you can commit it.

Done in D2897

wraitii planned changes to this revision.Sat, Aug 1, 5:33 PM

Will rebase after SM52